mdp3_ppp.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239
  1. /* Copyright (c) 2007, 2013 The Linux Foundation. All rights reserved.
  2. * Copyright (C) 2007 Google Incorporated
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License version 2, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/file.h>
  14. #include <linux/io.h>
  15. #include <linux/kernel.h>
  16. #include <linux/major.h>
  17. #include <linux/slab.h>
  18. #include <linux/types.h>
  19. #include <linux/uaccess.h>
  20. #include <linux/sched.h>
  21. #include <linux/mutex.h>
  22. #include <linux/sync.h>
  23. #include <linux/sw_sync.h>
  24. #include "linux/proc_fs.h"
  25. #include <linux/delay.h>
  26. #include "mdss_fb.h"
  27. #include "mdp3_ppp.h"
  28. #include "mdp3_hwio.h"
  29. #include "mdp3.h"
  30. #include "mdss_debug.h"
  31. #define MDP_IS_IMGTYPE_BAD(x) ((x) >= MDP_IMGTYPE_LIMIT)
  32. #define MDP_RELEASE_BW_TIMEOUT 50
  33. #define MDP_BLIT_CLK_RATE 200000000
  34. #define MDP_PPP_MAX_BPP 4
  35. #define MDP_PPP_DYNAMIC_FACTOR 3
  36. #define MDP_PPP_MAX_READ_WRITE 3
  37. #define ENABLE_SOLID_FILL 0x2
  38. #define DISABLE_SOLID_FILL 0x0
  39. static const bool valid_fmt[MDP_IMGTYPE_LIMIT] = {
  40. [MDP_RGB_565] = true,
  41. [MDP_BGR_565] = true,
  42. [MDP_RGB_888] = true,
  43. [MDP_BGR_888] = true,
  44. [MDP_BGRA_8888] = true,
  45. [MDP_RGBA_8888] = true,
  46. [MDP_ARGB_8888] = true,
  47. [MDP_XRGB_8888] = true,
  48. [MDP_RGBX_8888] = true,
  49. [MDP_Y_CRCB_H2V2] = true,
  50. [MDP_Y_CBCR_H2V2] = true,
  51. [MDP_Y_CBCR_H2V2_ADRENO] = true,
  52. [MDP_Y_CBCR_H2V2_VENUS] = true,
  53. [MDP_YCRYCB_H2V1] = true,
  54. [MDP_Y_CBCR_H2V1] = true,
  55. [MDP_Y_CRCB_H2V1] = true,
  56. [MDP_BGRX_8888] = true,
  57. };
  58. #define MAX_LIST_WINDOW 16
  59. #define MDP3_PPP_MAX_LIST_REQ 8
  60. struct blit_req_list {
  61. int count;
  62. struct mdp_blit_req req_list[MAX_LIST_WINDOW];
  63. struct mdp3_img_data src_data[MAX_LIST_WINDOW];
  64. struct mdp3_img_data dst_data[MAX_LIST_WINDOW];
  65. struct sync_fence *acq_fen[MDP_MAX_FENCE_FD];
  66. u32 acq_fen_cnt;
  67. int cur_rel_fen_fd;
  68. struct sync_pt *cur_rel_sync_pt;
  69. struct sync_fence *cur_rel_fence;
  70. struct sync_fence *last_rel_fence;
  71. };
  72. struct blit_req_queue {
  73. struct blit_req_list req[MDP3_PPP_MAX_LIST_REQ];
  74. int count;
  75. int push_idx;
  76. int pop_idx;
  77. };
  78. struct ppp_status {
  79. bool wait_for_pop;
  80. struct completion ppp_comp;
  81. struct completion pop_q_comp;
  82. struct mutex req_mutex; /* Protect request queue */
  83. struct mutex config_ppp_mutex; /* Only one client configure register */
  84. struct msm_fb_data_type *mfd;
  85. struct work_struct blit_work;
  86. struct blit_req_queue req_q;
  87. struct sw_sync_timeline *timeline;
  88. int timeline_value;
  89. struct timer_list free_bw_timer;
  90. struct work_struct free_bw_work;
  91. bool bw_on;
  92. bool bw_optimal;
  93. };
  94. static struct ppp_status *ppp_stat;
  95. int ppp_get_bpp(uint32_t format, uint32_t fb_format)
  96. {
  97. int bpp = -EINVAL;
  98. if (format == MDP_FB_FORMAT)
  99. format = fb_format;
  100. bpp = ppp_bpp(format);
  101. if (bpp <= 0)
  102. pr_err("%s incorrect format %d\n", __func__, format);
  103. return bpp;
  104. }
  105. int mdp3_ppp_get_img(struct mdp_img *img, struct mdp_blit_req *req,
  106. struct mdp3_img_data *data)
  107. {
  108. struct msmfb_data fb_data;
  109. uint32_t stride;
  110. int bpp = ppp_bpp(img->format);
  111. if (bpp <= 0) {
  112. pr_err("%s incorrect format %d\n", __func__, img->format);
  113. return -EINVAL;
  114. }
  115. fb_data.flags = img->priv;
  116. fb_data.memory_id = img->memory_id;
  117. fb_data.offset = 0;
  118. stride = img->width * bpp;
  119. data->padding = 16 * stride;
  120. return mdp3_get_img(&fb_data, data, MDP3_CLIENT_PPP);
  121. }
  122. /* Check format */
  123. int mdp3_ppp_verify_fmt(struct mdp_blit_req *req)
  124. {
  125. if (MDP_IS_IMGTYPE_BAD(req->src.format) ||
  126. MDP_IS_IMGTYPE_BAD(req->dst.format)) {
  127. pr_err("%s: Color format out of range\n", __func__);
  128. return -EINVAL;
  129. }
  130. if (!valid_fmt[req->src.format] ||
  131. !valid_fmt[req->dst.format]) {
  132. pr_err("%s: Color format not supported\n", __func__);
  133. return -EINVAL;
  134. }
  135. return 0;
  136. }
  137. /* Check resolution */
  138. int mdp3_ppp_verify_res(struct mdp_blit_req *req)
  139. {
  140. if ((req->src.width == 0) || (req->src.height == 0) ||
  141. (req->src_rect.w == 0) || (req->src_rect.h == 0) ||
  142. (req->dst.width == 0) || (req->dst.height == 0) ||
  143. (req->dst_rect.w == 0) || (req->dst_rect.h == 0)) {
  144. pr_err("%s: Height/width can't be 0\n", __func__);
  145. return -EINVAL;
  146. }
  147. if (((req->src_rect.x + req->src_rect.w) > req->src.width) ||
  148. ((req->src_rect.y + req->src_rect.h) > req->src.height)) {
  149. pr_err("%s: src roi larger than boundary\n", __func__);
  150. return -EINVAL;
  151. }
  152. if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) ||
  153. ((req->dst_rect.y + req->dst_rect.h) > req->dst.height)) {
  154. pr_err("%s: dst roi larger than boundary\n", __func__);
  155. return -EINVAL;
  156. }
  157. return 0;
  158. }
  159. /* scaling range check */
  160. int mdp3_ppp_verify_scale(struct mdp_blit_req *req)
  161. {
  162. u32 src_width, src_height, dst_width, dst_height;
  163. src_width = req->src_rect.w;
  164. src_height = req->src_rect.h;
  165. if (req->flags & MDP_ROT_90) {
  166. dst_width = req->dst_rect.h;
  167. dst_height = req->dst_rect.w;
  168. } else {
  169. dst_width = req->dst_rect.w;
  170. dst_height = req->dst_rect.h;
  171. }
  172. switch (req->dst.format) {
  173. case MDP_Y_CRCB_H2V2:
  174. case MDP_Y_CBCR_H2V2:
  175. src_width = (src_width / 2) * 2;
  176. src_height = (src_height / 2) * 2;
  177. dst_width = (dst_width / 2) * 2;
  178. dst_height = (dst_height / 2) * 2;
  179. break;
  180. case MDP_Y_CRCB_H2V1:
  181. case MDP_Y_CBCR_H2V1:
  182. case MDP_YCRYCB_H2V1:
  183. src_width = (src_width / 2) * 2;
  184. dst_width = (dst_width / 2) * 2;
  185. break;
  186. default:
  187. break;
  188. }
  189. if (((MDP_SCALE_Q_FACTOR * dst_width) / src_width >
  190. MDP_MAX_X_SCALE_FACTOR)
  191. || ((MDP_SCALE_Q_FACTOR * dst_width) / src_width <
  192. MDP_MIN_X_SCALE_FACTOR)) {
  193. pr_err("%s: x req scale factor beyond capability\n", __func__);
  194. return -EINVAL;
  195. }
  196. if (((MDP_SCALE_Q_FACTOR * dst_height) / src_height >
  197. MDP_MAX_Y_SCALE_FACTOR)
  198. || ((MDP_SCALE_Q_FACTOR * dst_height) / src_height <
  199. MDP_MIN_Y_SCALE_FACTOR)) {
  200. pr_err("%s: y req scale factor beyond capability\n", __func__);
  201. return -EINVAL;
  202. }
  203. return 0;
  204. }
  205. /* operation check */
  206. int mdp3_ppp_verify_op(struct mdp_blit_req *req)
  207. {
  208. if (req->flags & MDP_DEINTERLACE) {
  209. pr_err("\n%s(): deinterlace not supported", __func__);
  210. return -EINVAL;
  211. }
  212. if (req->flags & MDP_SHARPENING) {
  213. pr_err("\n%s(): sharpening not supported", __func__);
  214. return -EINVAL;
  215. }
  216. return 0;
  217. }
  218. int mdp3_ppp_verify_req(struct mdp_blit_req *req)
  219. {
  220. int rc;
  221. if (req == NULL) {
  222. pr_err("%s: req == null\n", __func__);
  223. return -EINVAL;
  224. }
  225. rc = mdp3_ppp_verify_fmt(req);
  226. rc |= mdp3_ppp_verify_res(req);
  227. rc |= mdp3_ppp_verify_scale(req);
  228. rc |= mdp3_ppp_verify_op(req);
  229. return rc;
  230. }
  231. int mdp3_ppp_pipe_wait(void)
  232. {
  233. int ret = 1;
  234. /*
  235. * wait 200 ms for ppp operation to complete before declaring
  236. * the MDP hung
  237. */
  238. ret = wait_for_completion_timeout(
  239. &ppp_stat->ppp_comp, msecs_to_jiffies(200));
  240. if (!ret)
  241. pr_err("%s: Timed out waiting for the MDP.\n",
  242. __func__);
  243. return ret;
  244. }
  245. uint32_t mdp3_calc_tpval(struct ppp_img_desc *img, uint32_t old_tp)
  246. {
  247. uint32_t tpVal;
  248. uint8_t plane_tp;
  249. tpVal = 0;
  250. if ((img->color_fmt == MDP_RGB_565)
  251. || (img->color_fmt == MDP_BGR_565)) {
  252. /* transparent color conversion into 24 bpp */
  253. plane_tp = (uint8_t) ((old_tp & 0xF800) >> 11);
  254. tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16;
  255. plane_tp = (uint8_t) (old_tp & 0x1F);
  256. tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8;
  257. plane_tp = (uint8_t) ((old_tp & 0x7E0) >> 5);
  258. tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4));
  259. } else {
  260. /* 24bit RGB to RBG conversion */
  261. tpVal = (old_tp & 0xFF00) >> 8;
  262. tpVal |= (old_tp & 0xFF) << 8;
  263. tpVal |= (old_tp & 0xFF0000);
  264. }
  265. return tpVal;
  266. }
  267. static void mdp3_ppp_intr_handler(int type, void *arg)
  268. {
  269. complete(&ppp_stat->ppp_comp);
  270. }
  271. static int mdp3_ppp_callback_setup(void)
  272. {
  273. int rc;
  274. struct mdp3_intr_cb ppp_done_cb = {
  275. .cb = mdp3_ppp_intr_handler,
  276. .data = NULL,
  277. };
  278. rc = mdp3_set_intr_callback(MDP3_PPP_DONE, &ppp_done_cb);
  279. return rc;
  280. }
  281. void mdp3_ppp_kickoff(void)
  282. {
  283. init_completion(&ppp_stat->ppp_comp);
  284. mdp3_irq_enable(MDP3_PPP_DONE);
  285. ppp_enable();
  286. ATRACE_BEGIN("mdp3_wait_for_ppp_comp");
  287. mdp3_ppp_pipe_wait();
  288. ATRACE_END("mdp3_wait_for_ppp_comp");
  289. mdp3_irq_disable(MDP3_PPP_DONE);
  290. }
  291. int mdp3_ppp_vote_update(struct msm_fb_data_type *mfd)
  292. {
  293. struct mdss_panel_info *panel_info = mfd->panel_info;
  294. uint64_t req_bw = 0, ab = 0, ib = 0;
  295. int rate = 0;
  296. int rc = 0;
  297. if (!ppp_stat->bw_on)
  298. pr_err("%s: PPP vote update in wrong state\n", __func__);
  299. rate = MDP_BLIT_CLK_RATE;
  300. req_bw = panel_info->xres * panel_info->yres *
  301. panel_info->mipi.frame_rate *
  302. MDP_PPP_MAX_BPP *
  303. MDP_PPP_DYNAMIC_FACTOR *
  304. MDP_PPP_MAX_READ_WRITE;
  305. ib = (req_bw * 3) / 2;
  306. if (ppp_stat->bw_optimal)
  307. ab = ib / 2;
  308. else
  309. ab = req_bw;
  310. rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib);
  311. if (rc < 0) {
  312. pr_err("%s: scale_set_quota failed\n", __func__);
  313. return rc;
  314. }
  315. return rc;
  316. }
  317. int mdp3_ppp_turnon(struct msm_fb_data_type *mfd, int on_off)
  318. {
  319. struct mdss_panel_info *panel_info = mfd->panel_info;
  320. uint64_t req_bw = 0, ab = 0, ib = 0;
  321. int rate = 0;
  322. int rc;
  323. if (on_off) {
  324. rate = MDP_BLIT_CLK_RATE;
  325. req_bw = panel_info->xres * panel_info->yres *
  326. panel_info->mipi.frame_rate *
  327. MDP_PPP_MAX_BPP *
  328. MDP_PPP_DYNAMIC_FACTOR *
  329. MDP_PPP_MAX_READ_WRITE;
  330. ib = (req_bw * 3) / 2;
  331. if (ppp_stat->bw_optimal)
  332. ab = ib / 2;
  333. else
  334. ab = req_bw;
  335. }
  336. mdp3_clk_set_rate(MDP3_CLK_CORE, rate, MDP3_CLIENT_PPP);
  337. rc = mdp3_res_update(on_off, 0, MDP3_CLIENT_PPP);
  338. if (rc < 0) {
  339. pr_err("%s: mdp3_clk_enable failed\n", __func__);
  340. return rc;
  341. }
  342. rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib);
  343. if (rc < 0) {
  344. mdp3_res_update(!on_off, 0, MDP3_CLIENT_PPP);
  345. pr_err("%s: scale_set_quota failed\n", __func__);
  346. return rc;
  347. }
  348. ppp_stat->bw_on = on_off;
  349. return 0;
  350. }
  351. bool mdp3_optimal_bw(struct blit_req_list *req)
  352. {
  353. int i, solid_fill = 0;
  354. if (!req || (ppp_stat->req_q.count > 1))
  355. return false;
  356. for (i = 0; i < req->count; i++) {
  357. if (req->req_list[i].flags & MDP_SOLID_FILL)
  358. solid_fill++;
  359. }
  360. if ((req->count - solid_fill) <= 1)
  361. return true;
  362. return false;
  363. }
  364. void mdp3_start_ppp(struct ppp_blit_op *blit_op)
  365. {
  366. /* Wait for the pipe to clear */
  367. if (MDP3_REG_READ(MDP3_REG_DISPLAY_STATUS) &
  368. MDP3_PPP_ACTIVE) {
  369. pr_err("ppp core is hung up on previous request\n");
  370. return;
  371. }
  372. config_ppp_op_mode(blit_op);
  373. if (blit_op->solid_fill) {
  374. MDP3_REG_WRITE(0x10138, 0x10000000);
  375. MDP3_REG_WRITE(0x1014c, 0xffffffff);
  376. MDP3_REG_WRITE(0x101b8, 0);
  377. MDP3_REG_WRITE(0x101bc, 0);
  378. MDP3_REG_WRITE(0x1013c, 0);
  379. MDP3_REG_WRITE(0x10140, 0);
  380. MDP3_REG_WRITE(0x10144, 0);
  381. MDP3_REG_WRITE(0x10148, 0);
  382. MDP3_REG_WRITE(MDP3_TFETCH_FILL_COLOR,
  383. blit_op->solid_fill_color);
  384. MDP3_REG_WRITE(MDP3_TFETCH_SOLID_FILL,
  385. ENABLE_SOLID_FILL);
  386. } else {
  387. MDP3_REG_WRITE(MDP3_TFETCH_SOLID_FILL,
  388. DISABLE_SOLID_FILL);
  389. }
  390. mdp3_ppp_kickoff();
  391. }
  392. static int solid_fill_workaround(struct mdp_blit_req *req,
  393. struct ppp_blit_op *blit_op)
  394. {
  395. /* Make width 2 when there is a solid fill of width 1, and make
  396. sure width does not become zero while trying to avoid odd width */
  397. if (blit_op->dst.roi.width == 1) {
  398. if (req->dst_rect.x + 2 > req->dst.width) {
  399. pr_err("%s: Unable to handle solid fill of width 1",
  400. __func__);
  401. return -EINVAL;
  402. }
  403. blit_op->dst.roi.width = 2;
  404. }
  405. if (blit_op->src.roi.width == 1) {
  406. if (req->src_rect.x + 2 > req->src.width) {
  407. pr_err("%s: Unable to handle solid fill of width 1",
  408. __func__);
  409. return -EINVAL;
  410. }
  411. blit_op->src.roi.width = 2;
  412. }
  413. /* Avoid odd width, as it could hang ppp during solid fill */
  414. blit_op->dst.roi.width = (blit_op->dst.roi.width / 2) * 2;
  415. blit_op->src.roi.width = (blit_op->src.roi.width / 2) * 2;
  416. /* Avoid RGBA format, as it could hang ppp during solid fill */
  417. if (blit_op->src.color_fmt == MDP_RGBA_8888)
  418. blit_op->src.color_fmt = MDP_RGBX_8888;
  419. if (blit_op->dst.color_fmt == MDP_RGBA_8888)
  420. blit_op->dst.color_fmt = MDP_RGBX_8888;
  421. return 0;
  422. }
  423. static int mdp3_ppp_process_req(struct ppp_blit_op *blit_op,
  424. struct mdp_blit_req *req, struct mdp3_img_data *src_data,
  425. struct mdp3_img_data *dst_data)
  426. {
  427. unsigned long srcp0_start, srcp0_len, dst_start, dst_len;
  428. uint32_t dst_width, dst_height;
  429. int ret = 0;
  430. srcp0_start = (unsigned long) src_data->addr;
  431. srcp0_len = (unsigned long) src_data->len;
  432. dst_start = (unsigned long) dst_data->addr;
  433. dst_len = (unsigned long) dst_data->len;
  434. blit_op->dst.prop.width = req->dst.width;
  435. blit_op->dst.prop.height = req->dst.height;
  436. blit_op->dst.color_fmt = req->dst.format;
  437. blit_op->dst.p0 = (void *) dst_start;
  438. blit_op->dst.p0 += req->dst.offset;
  439. blit_op->dst.roi.x = req->dst_rect.x;
  440. blit_op->dst.roi.y = req->dst_rect.y;
  441. blit_op->dst.roi.width = req->dst_rect.w;
  442. blit_op->dst.roi.height = req->dst_rect.h;
  443. blit_op->src.roi.x = req->src_rect.x;
  444. blit_op->src.roi.y = req->src_rect.y;
  445. blit_op->src.roi.width = req->src_rect.w;
  446. blit_op->src.roi.height = req->src_rect.h;
  447. blit_op->src.prop.width = req->src.width;
  448. blit_op->src.color_fmt = req->src.format;
  449. blit_op->src.p0 = (void *) (srcp0_start + req->src.offset);
  450. if (blit_op->src.color_fmt == MDP_Y_CBCR_H2V2_ADRENO)
  451. blit_op->src.p1 =
  452. (void *) ((uint32_t) blit_op->src.p0 +
  453. ALIGN((ALIGN(req->src.width, 32) *
  454. ALIGN(req->src.height, 32)), 4096));
  455. else if (blit_op->src.color_fmt == MDP_Y_CBCR_H2V2_VENUS)
  456. blit_op->src.p1 =
  457. (void *) ((uint32_t) blit_op->src.p0 +
  458. ALIGN((ALIGN(req->src.width, 128) *
  459. ALIGN(req->src.height, 32)), 4096));
  460. else
  461. blit_op->src.p1 = (void *) ((uint32_t) blit_op->src.p0 +
  462. req->src.width * req->src.height);
  463. if (req->flags & MDP_IS_FG)
  464. blit_op->mdp_op |= MDPOP_LAYER_IS_FG;
  465. /* blending check */
  466. if (req->transp_mask != MDP_TRANSP_NOP) {
  467. blit_op->mdp_op |= MDPOP_TRANSP;
  468. blit_op->blend.trans_color =
  469. mdp3_calc_tpval(&blit_op->src, req->transp_mask);
  470. } else {
  471. blit_op->blend.trans_color = 0;
  472. }
  473. req->alpha &= 0xff;
  474. if (req->alpha < MDP_ALPHA_NOP) {
  475. blit_op->mdp_op |= MDPOP_ALPHAB;
  476. blit_op->blend.const_alpha = req->alpha;
  477. } else {
  478. blit_op->blend.const_alpha = 0xff;
  479. }
  480. /* rotation check */
  481. if (req->flags & MDP_FLIP_LR)
  482. blit_op->mdp_op |= MDPOP_LR;
  483. if (req->flags & MDP_FLIP_UD)
  484. blit_op->mdp_op |= MDPOP_UD;
  485. if (req->flags & MDP_ROT_90)
  486. blit_op->mdp_op |= MDPOP_ROT90;
  487. if (req->flags & MDP_DITHER)
  488. blit_op->mdp_op |= MDPOP_DITHER;
  489. if (req->flags & MDP_BLEND_FG_PREMULT)
  490. blit_op->mdp_op |= MDPOP_FG_PM_ALPHA;
  491. /* scale check */
  492. if (req->flags & MDP_ROT_90) {
  493. dst_width = req->dst_rect.h;
  494. dst_height = req->dst_rect.w;
  495. } else {
  496. dst_width = req->dst_rect.w;
  497. dst_height = req->dst_rect.h;
  498. }
  499. if ((blit_op->src.roi.width != dst_width) ||
  500. (blit_op->src.roi.height != dst_height))
  501. blit_op->mdp_op |= MDPOP_ASCALE;
  502. if (req->flags & MDP_BLUR)
  503. blit_op->mdp_op |= MDPOP_ASCALE | MDPOP_BLUR;
  504. if (req->flags & MDP_SOLID_FILL) {
  505. ret = solid_fill_workaround(req, blit_op);
  506. if (ret)
  507. return ret;
  508. blit_op->solid_fill_color = (req->const_color.g & 0xFF)|
  509. (req->const_color.r & 0xFF) << 8 |
  510. (req->const_color.b & 0xFF) << 16 |
  511. (req->const_color.alpha & 0xFF) << 24;
  512. blit_op->solid_fill = true;
  513. } else {
  514. blit_op->solid_fill = false;
  515. }
  516. return ret;
  517. }
  518. static void mdp3_ppp_tile_workaround(struct ppp_blit_op *blit_op,
  519. struct mdp_blit_req *req)
  520. {
  521. int dst_h, src_w, i;
  522. uint32_t mdp_op = blit_op->mdp_op;
  523. void *src_p0 = blit_op->src.p0;
  524. void *src_p1 = blit_op->src.p1;
  525. void *dst_p0 = blit_op->dst.p0;
  526. src_w = req->src_rect.w;
  527. dst_h = blit_op->dst.roi.height;
  528. /* bg tile fetching HW workaround */
  529. for (i = 0; i < (req->dst_rect.h / 16); i++) {
  530. /* this tile size */
  531. blit_op->dst.roi.height = 16;
  532. blit_op->src.roi.width =
  533. (16 * req->src_rect.w) / req->dst_rect.h;
  534. /* if it's out of scale range... */
  535. if (((MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
  536. blit_op->src.roi.width) > MDP_MAX_X_SCALE_FACTOR)
  537. blit_op->src.roi.width =
  538. (MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
  539. MDP_MAX_X_SCALE_FACTOR;
  540. else if (((MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
  541. blit_op->src.roi.width) < MDP_MIN_X_SCALE_FACTOR)
  542. blit_op->src.roi.width =
  543. (MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
  544. MDP_MIN_X_SCALE_FACTOR;
  545. mdp3_start_ppp(blit_op);
  546. /* next tile location */
  547. blit_op->dst.roi.y += 16;
  548. blit_op->src.roi.x += blit_op->src.roi.width;
  549. /* this is for a remainder update */
  550. dst_h -= 16;
  551. src_w -= blit_op->src.roi.width;
  552. /* restore parameters that may have been overwritten */
  553. blit_op->mdp_op = mdp_op;
  554. blit_op->src.p0 = src_p0;
  555. blit_op->src.p1 = src_p1;
  556. blit_op->dst.p0 = dst_p0;
  557. }
  558. if ((dst_h < 0) || (src_w < 0))
  559. pr_err
  560. ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n",
  561. __LINE__);
  562. /* remainder update */
  563. if ((dst_h > 0) && (src_w > 0)) {
  564. u32 tmp_v;
  565. blit_op->dst.roi.height = dst_h;
  566. blit_op->src.roi.width = src_w;
  567. if (((MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
  568. blit_op->src.roi.width) > MDP_MAX_X_SCALE_FACTOR) {
  569. tmp_v =
  570. (MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
  571. MDP_MAX_X_SCALE_FACTOR +
  572. ((MDP_SCALE_Q_FACTOR *
  573. blit_op->dst.roi.height) %
  574. MDP_MAX_X_SCALE_FACTOR ? 1 : 0);
  575. /* move x location as roi width gets bigger */
  576. blit_op->src.roi.x -= tmp_v - blit_op->src.roi.width;
  577. blit_op->src.roi.width = tmp_v;
  578. } else if (((MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
  579. blit_op->src.roi.width) < MDP_MIN_X_SCALE_FACTOR) {
  580. tmp_v =
  581. (MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
  582. MDP_MIN_X_SCALE_FACTOR +
  583. ((MDP_SCALE_Q_FACTOR *
  584. blit_op->dst.roi.height) %
  585. MDP_MIN_X_SCALE_FACTOR ? 1 : 0);
  586. /*
  587. * we don't move x location for continuity of
  588. * source image
  589. */
  590. blit_op->src.roi.width = tmp_v;
  591. }
  592. mdp3_start_ppp(blit_op);
  593. }
  594. }
  595. static int mdp3_ppp_blit(struct msm_fb_data_type *mfd,
  596. struct mdp_blit_req *req, struct mdp3_img_data *src_data,
  597. struct mdp3_img_data *dst_data)
  598. {
  599. struct ppp_blit_op blit_op;
  600. int ret = 0;
  601. memset(&blit_op, 0, sizeof(blit_op));
  602. if (req->dst.format == MDP_FB_FORMAT)
  603. req->dst.format = mfd->fb_imgType;
  604. if (req->src.format == MDP_FB_FORMAT)
  605. req->src.format = mfd->fb_imgType;
  606. if (mdp3_ppp_verify_req(req)) {
  607. pr_err("%s: invalid image!\n", __func__);
  608. return -EINVAL;
  609. }
  610. ret = mdp3_ppp_process_req(&blit_op, req, src_data, dst_data);
  611. if (ret) {
  612. pr_err("%s: Failed to process the blit request", __func__);
  613. return ret;
  614. }
  615. if (((blit_op.mdp_op & (MDPOP_TRANSP | MDPOP_ALPHAB)) ||
  616. (req->src.format == MDP_ARGB_8888) ||
  617. (req->src.format == MDP_BGRA_8888) ||
  618. (req->src.format == MDP_RGBA_8888)) &&
  619. (blit_op.mdp_op & MDPOP_ROT90) && (req->dst_rect.w <= 16)) {
  620. mdp3_ppp_tile_workaround(&blit_op, req);
  621. } else {
  622. mdp3_start_ppp(&blit_op);
  623. }
  624. return 0;
  625. }
  626. static int mdp3_ppp_blit_workaround(struct msm_fb_data_type *mfd,
  627. struct mdp_blit_req *req, unsigned int remainder,
  628. struct mdp3_img_data *src_data,
  629. struct mdp3_img_data *dst_data)
  630. {
  631. int ret;
  632. struct mdp_blit_req splitreq;
  633. int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1;
  634. int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1;
  635. /* make new request as provide by user */
  636. splitreq = *req;
  637. /* break dest roi at width*/
  638. d_y_0 = d_y_1 = req->dst_rect.y;
  639. d_h_0 = d_h_1 = req->dst_rect.h;
  640. d_x_0 = req->dst_rect.x;
  641. if (remainder == 14 || remainder == 6)
  642. d_w_1 = req->dst_rect.w / 2;
  643. else
  644. d_w_1 = (req->dst_rect.w - 1) / 2 - 1;
  645. d_w_0 = req->dst_rect.w - d_w_1;
  646. d_x_1 = d_x_0 + d_w_0;
  647. /* blit first region */
  648. if (((splitreq.flags & 0x07) == 0x07) ||
  649. ((splitreq.flags & 0x07) == 0x05) ||
  650. ((splitreq.flags & 0x07) == 0x02) ||
  651. ((splitreq.flags & 0x07) == 0x0)) {
  652. if (splitreq.flags & MDP_ROT_90) {
  653. s_x_0 = s_x_1 = req->src_rect.x;
  654. s_w_0 = s_w_1 = req->src_rect.w;
  655. s_y_0 = req->src_rect.y;
  656. s_h_1 = (req->src_rect.h * d_w_1) /
  657. req->dst_rect.w;
  658. s_h_0 = req->src_rect.h - s_h_1;
  659. s_y_1 = s_y_0 + s_h_0;
  660. if (d_w_1 >= 8 * s_h_1) {
  661. s_h_1++;
  662. s_y_1--;
  663. }
  664. } else {
  665. s_y_0 = s_y_1 = req->src_rect.y;
  666. s_h_0 = s_h_1 = req->src_rect.h;
  667. s_x_0 = req->src_rect.x;
  668. s_w_1 = (req->src_rect.w * d_w_1) /
  669. req->dst_rect.w;
  670. s_w_0 = req->src_rect.w - s_w_1;
  671. s_x_1 = s_x_0 + s_w_0;
  672. if (d_w_1 >= 8 * s_w_1) {
  673. s_w_1++;
  674. s_x_1--;
  675. }
  676. }
  677. splitreq.src_rect.h = s_h_0;
  678. splitreq.src_rect.y = s_y_0;
  679. splitreq.dst_rect.h = d_h_0;
  680. splitreq.dst_rect.y = d_y_0;
  681. splitreq.src_rect.x = s_x_0;
  682. splitreq.src_rect.w = s_w_0;
  683. splitreq.dst_rect.x = d_x_0;
  684. splitreq.dst_rect.w = d_w_0;
  685. } else {
  686. if (splitreq.flags & MDP_ROT_90) {
  687. s_x_0 = s_x_1 = req->src_rect.x;
  688. s_w_0 = s_w_1 = req->src_rect.w;
  689. s_y_0 = req->src_rect.y;
  690. s_h_1 = (req->src_rect.h * d_w_0) /
  691. req->dst_rect.w;
  692. s_h_0 = req->src_rect.h - s_h_1;
  693. s_y_1 = s_y_0 + s_h_0;
  694. if (d_w_0 >= 8 * s_h_1) {
  695. s_h_1++;
  696. s_y_1--;
  697. }
  698. } else {
  699. s_y_0 = s_y_1 = req->src_rect.y;
  700. s_h_0 = s_h_1 = req->src_rect.h;
  701. s_x_0 = req->src_rect.x;
  702. s_w_1 = (req->src_rect.w * d_w_0) /
  703. req->dst_rect.w;
  704. s_w_0 = req->src_rect.w - s_w_1;
  705. s_x_1 = s_x_0 + s_w_0;
  706. if (d_w_0 >= 8 * s_w_1) {
  707. s_w_1++;
  708. s_x_1--;
  709. }
  710. }
  711. splitreq.src_rect.h = s_h_0;
  712. splitreq.src_rect.y = s_y_0;
  713. splitreq.dst_rect.h = d_h_1;
  714. splitreq.dst_rect.y = d_y_1;
  715. splitreq.src_rect.x = s_x_0;
  716. splitreq.src_rect.w = s_w_0;
  717. splitreq.dst_rect.x = d_x_1;
  718. splitreq.dst_rect.w = d_w_1;
  719. }
  720. /* No need to split in height */
  721. ret = mdp3_ppp_blit(mfd, &splitreq, src_data, dst_data);
  722. if (ret)
  723. return ret;
  724. /* blit second region */
  725. if (((splitreq.flags & 0x07) == 0x07) ||
  726. ((splitreq.flags & 0x07) == 0x05) ||
  727. ((splitreq.flags & 0x07) == 0x02) ||
  728. ((splitreq.flags & 0x07) == 0x0)) {
  729. splitreq.src_rect.h = s_h_1;
  730. splitreq.src_rect.y = s_y_1;
  731. splitreq.dst_rect.h = d_h_1;
  732. splitreq.dst_rect.y = d_y_1;
  733. splitreq.src_rect.x = s_x_1;
  734. splitreq.src_rect.w = s_w_1;
  735. splitreq.dst_rect.x = d_x_1;
  736. splitreq.dst_rect.w = d_w_1;
  737. } else {
  738. splitreq.src_rect.h = s_h_1;
  739. splitreq.src_rect.y = s_y_1;
  740. splitreq.dst_rect.h = d_h_0;
  741. splitreq.dst_rect.y = d_y_0;
  742. splitreq.src_rect.x = s_x_1;
  743. splitreq.src_rect.w = s_w_1;
  744. splitreq.dst_rect.x = d_x_0;
  745. splitreq.dst_rect.w = d_w_0;
  746. }
  747. /* No need to split in height ... just width */
  748. return mdp3_ppp_blit(mfd, &splitreq, src_data, dst_data);
  749. }
  750. int mdp3_ppp_start_blit(struct msm_fb_data_type *mfd,
  751. struct mdp_blit_req *req,
  752. struct mdp3_img_data *src_data,
  753. struct mdp3_img_data *dst_data)
  754. {
  755. int ret;
  756. unsigned int remainder = 0, is_bpp_4 = 0;
  757. if (unlikely(req->src_rect.h == 0 || req->src_rect.w == 0)) {
  758. pr_err("mdp_ppp: src img of zero size!\n");
  759. return -EINVAL;
  760. }
  761. if (unlikely(req->dst_rect.h == 0 || req->dst_rect.w == 0))
  762. return 0;
  763. /* MDP width split workaround */
  764. remainder = (req->dst_rect.w) % 16;
  765. ret = ppp_get_bpp(req->dst.format, mfd->fb_imgType);
  766. if (ret <= 0) {
  767. pr_err("mdp_ppp: incorrect bpp!\n");
  768. return -EINVAL;
  769. }
  770. is_bpp_4 = (ret == 4) ? 1 : 0;
  771. if ((is_bpp_4 && (remainder == 6 || remainder == 14)) &&
  772. !(req->flags & MDP_SOLID_FILL))
  773. ret = mdp3_ppp_blit_workaround(mfd, req, remainder,
  774. src_data, dst_data);
  775. else
  776. ret = mdp3_ppp_blit(mfd, req, src_data, dst_data);
  777. return ret;
  778. }
  779. void mdp3_ppp_wait_for_fence(struct blit_req_list *req)
  780. {
  781. int i, ret = 0;
  782. ATRACE_BEGIN(__func__);
  783. /* buf sync */
  784. for (i = 0; i < req->acq_fen_cnt; i++) {
  785. ret = sync_fence_wait(req->acq_fen[i],
  786. WAIT_FENCE_FINAL_TIMEOUT);
  787. if (ret < 0) {
  788. pr_err("%s: sync_fence_wait failed! ret = %x\n",
  789. __func__, ret);
  790. break;
  791. }
  792. sync_fence_put(req->acq_fen[i]);
  793. }
  794. ATRACE_END(__func__);
  795. if (ret < 0) {
  796. while (i < req->acq_fen_cnt) {
  797. sync_fence_put(req->acq_fen[i]);
  798. i++;
  799. }
  800. }
  801. req->acq_fen_cnt = 0;
  802. }
  803. void mdp3_ppp_signal_timeline(struct blit_req_list *req)
  804. {
  805. sw_sync_timeline_inc(ppp_stat->timeline, 1);
  806. req->last_rel_fence = req->cur_rel_fence;
  807. req->cur_rel_fence = 0;
  808. }
  809. static void mdp3_ppp_deinit_buf_sync(struct blit_req_list *req)
  810. {
  811. int i;
  812. put_unused_fd(req->cur_rel_fen_fd);
  813. sync_fence_put(req->cur_rel_fence);
  814. req->cur_rel_fence = NULL;
  815. req->cur_rel_fen_fd = 0;
  816. ppp_stat->timeline_value--;
  817. for (i = 0; i < req->acq_fen_cnt; i++)
  818. sync_fence_put(req->acq_fen[i]);
  819. req->acq_fen_cnt = 0;
  820. }
  821. static int mdp3_ppp_handle_buf_sync(struct blit_req_list *req,
  822. struct mdp_buf_sync *buf_sync)
  823. {
  824. int i, fence_cnt = 0, ret = 0;
  825. int acq_fen_fd[MDP_MAX_FENCE_FD];
  826. struct sync_fence *fence;
  827. if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
  828. (ppp_stat->timeline == NULL))
  829. return -EINVAL;
  830. if (buf_sync->acq_fen_fd_cnt)
  831. ret = copy_from_user(acq_fen_fd, buf_sync->acq_fen_fd,
  832. buf_sync->acq_fen_fd_cnt * sizeof(int));
  833. if (ret) {
  834. pr_err("%s: copy_from_user failed\n", __func__);
  835. return ret;
  836. }
  837. for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
  838. fence = sync_fence_fdget(acq_fen_fd[i]);
  839. if (fence == NULL) {
  840. pr_info("%s: null fence! i=%d fd=%d\n", __func__, i,
  841. acq_fen_fd[i]);
  842. ret = -EINVAL;
  843. break;
  844. }
  845. req->acq_fen[i] = fence;
  846. }
  847. fence_cnt = i;
  848. if (ret)
  849. goto buf_sync_err_1;
  850. req->acq_fen_cnt = fence_cnt;
  851. if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
  852. mdp3_ppp_wait_for_fence(req);
  853. req->cur_rel_sync_pt = sw_sync_pt_create(ppp_stat->timeline,
  854. ppp_stat->timeline_value++);
  855. if (req->cur_rel_sync_pt == NULL) {
  856. pr_err("%s: cannot create sync point\n", __func__);
  857. ret = -ENOMEM;
  858. goto buf_sync_err_2;
  859. }
  860. /* create fence */
  861. req->cur_rel_fence = sync_fence_create("ppp-fence",
  862. req->cur_rel_sync_pt);
  863. if (req->cur_rel_fence == NULL) {
  864. sync_pt_free(req->cur_rel_sync_pt);
  865. req->cur_rel_sync_pt = NULL;
  866. pr_err("%s: cannot create fence\n", __func__);
  867. ret = -ENOMEM;
  868. goto buf_sync_err_2;
  869. }
  870. /* create fd */
  871. return ret;
  872. buf_sync_err_2:
  873. ppp_stat->timeline_value--;
  874. buf_sync_err_1:
  875. for (i = 0; i < fence_cnt; i++)
  876. sync_fence_put(req->acq_fen[i]);
  877. req->acq_fen_cnt = 0;
  878. return ret;
  879. }
  880. void mdp3_ppp_req_push(struct blit_req_queue *req_q, struct blit_req_list *req)
  881. {
  882. int idx = req_q->push_idx;
  883. req_q->req[idx] = *req;
  884. req_q->count++;
  885. req_q->push_idx = (req_q->push_idx + 1) % MDP3_PPP_MAX_LIST_REQ;
  886. }
  887. struct blit_req_list *mdp3_ppp_next_req(struct blit_req_queue *req_q)
  888. {
  889. struct blit_req_list *req;
  890. if (req_q->count == 0)
  891. return NULL;
  892. req = &req_q->req[req_q->pop_idx];
  893. return req;
  894. }
  895. void mdp3_ppp_req_pop(struct blit_req_queue *req_q)
  896. {
  897. req_q->count--;
  898. req_q->pop_idx = (req_q->pop_idx + 1) % MDP3_PPP_MAX_LIST_REQ;
  899. }
  900. void mdp3_free_fw_timer_func(unsigned long arg)
  901. {
  902. schedule_work(&ppp_stat->free_bw_work);
  903. }
  904. static void mdp3_free_bw_wq_handler(struct work_struct *work)
  905. {
  906. struct msm_fb_data_type *mfd = ppp_stat->mfd;
  907. mutex_lock(&ppp_stat->config_ppp_mutex);
  908. if (ppp_stat->bw_on) {
  909. mdp3_ppp_turnon(mfd, 0);
  910. }
  911. mutex_unlock(&ppp_stat->config_ppp_mutex);
  912. }
  913. static void mdp3_ppp_blit_wq_handler(struct work_struct *work)
  914. {
  915. struct msm_fb_data_type *mfd = ppp_stat->mfd;
  916. struct blit_req_list *req;
  917. int i, rc = 0;
  918. mutex_lock(&ppp_stat->config_ppp_mutex);
  919. req = mdp3_ppp_next_req(&ppp_stat->req_q);
  920. if (!req) {
  921. mutex_unlock(&ppp_stat->config_ppp_mutex);
  922. return;
  923. }
  924. if (!ppp_stat->bw_on) {
  925. ppp_stat->bw_optimal = mdp3_optimal_bw(req);
  926. mdp3_ppp_turnon(mfd, 1);
  927. if (rc < 0) {
  928. mutex_unlock(&ppp_stat->config_ppp_mutex);
  929. pr_err("%s: Enable ppp resources failed\n", __func__);
  930. return;
  931. }
  932. }
  933. while (req) {
  934. mdp3_ppp_wait_for_fence(req);
  935. ATRACE_BEGIN("mdp3_ppp_start");
  936. for (i = 0; i < req->count; i++) {
  937. if (!(req->req_list[i].flags & MDP_NO_BLIT)) {
  938. /* Do the actual blit. */
  939. if (!rc) {
  940. rc = mdp3_ppp_start_blit(mfd,
  941. &(req->req_list[i]),
  942. &req->src_data[i],
  943. &req->dst_data[i]);
  944. }
  945. mdp3_put_img(&req->src_data[i],
  946. MDP3_CLIENT_PPP);
  947. mdp3_put_img(&req->dst_data[i],
  948. MDP3_CLIENT_PPP);
  949. }
  950. }
  951. ATRACE_END("mdp3_ppp_start");
  952. /* Signal to release fence */
  953. mutex_lock(&ppp_stat->req_mutex);
  954. mdp3_ppp_signal_timeline(req);
  955. mdp3_ppp_req_pop(&ppp_stat->req_q);
  956. req = mdp3_ppp_next_req(&ppp_stat->req_q);
  957. if (ppp_stat->wait_for_pop)
  958. complete(&ppp_stat->pop_q_comp);
  959. mutex_unlock(&ppp_stat->req_mutex);
  960. if (req && (ppp_stat->bw_optimal != mdp3_optimal_bw(req))) {
  961. ppp_stat->bw_optimal = !ppp_stat->bw_optimal;
  962. mdp3_ppp_vote_update(mfd);
  963. }
  964. }
  965. mod_timer(&ppp_stat->free_bw_timer, jiffies +
  966. msecs_to_jiffies(MDP_RELEASE_BW_TIMEOUT));
  967. mutex_unlock(&ppp_stat->config_ppp_mutex);
  968. }
  969. int mdp3_ppp_parse_req(void __user *p,
  970. struct mdp_async_blit_req_list *req_list_header,
  971. int async)
  972. {
  973. struct blit_req_list *req;
  974. struct blit_req_queue *req_q = &ppp_stat->req_q;
  975. struct sync_fence *fence = NULL;
  976. int count, rc, idx, i;
  977. count = req_list_header->count;
  978. mutex_lock(&ppp_stat->req_mutex);
  979. while (req_q->count >= MDP3_PPP_MAX_LIST_REQ) {
  980. ppp_stat->wait_for_pop = true;
  981. mutex_unlock(&ppp_stat->req_mutex);
  982. rc = wait_for_completion_timeout(
  983. &ppp_stat->pop_q_comp, 5 * HZ);
  984. if (rc == 0) {
  985. /* This will only occur if there is serious problem */
  986. pr_err("%s: timeout exiting queuing request\n",
  987. __func__);
  988. return -EBUSY;
  989. }
  990. mutex_lock(&ppp_stat->req_mutex);
  991. ppp_stat->wait_for_pop = false;
  992. }
  993. idx = req_q->push_idx;
  994. req = &req_q->req[idx];
  995. if (copy_from_user(&req->req_list, p,
  996. sizeof(struct mdp_blit_req) * count)) {
  997. mutex_unlock(&ppp_stat->req_mutex);
  998. return -EFAULT;
  999. }
  1000. rc = mdp3_ppp_handle_buf_sync(req, &req_list_header->sync);
  1001. if (rc < 0) {
  1002. pr_err("%s: Failed create sync point\n", __func__);
  1003. mutex_unlock(&ppp_stat->req_mutex);
  1004. return rc;
  1005. }
  1006. req->count = count;
  1007. /* We need to grab ion handle while running in client thread */
  1008. for (i = 0; i < count; i++) {
  1009. rc = mdp3_ppp_get_img(&req->req_list[i].src,
  1010. &req->req_list[i], &req->src_data[i]);
  1011. if (rc < 0 || req->src_data[i].len == 0) {
  1012. pr_err("mdp_ppp: couldn't retrieve src img from mem\n");
  1013. goto parse_err_1;
  1014. }
  1015. rc = mdp3_ppp_get_img(&req->req_list[i].dst,
  1016. &req->req_list[i], &req->dst_data[i]);
  1017. if (rc < 0 || req->dst_data[i].len == 0) {
  1018. mdp3_put_img(&req->src_data[i], MDP3_CLIENT_PPP);
  1019. pr_err("mdp_ppp: couldn't retrieve dest img from mem\n");
  1020. goto parse_err_1;
  1021. }
  1022. }
  1023. if (async) {
  1024. req->cur_rel_fen_fd = get_unused_fd_flags(0);
  1025. if (req->cur_rel_fen_fd < 0) {
  1026. pr_err("%s: get_unused_fd_flags failed\n", __func__);
  1027. rc = -ENOMEM;
  1028. goto parse_err_1;
  1029. }
  1030. sync_fence_install(req->cur_rel_fence, req->cur_rel_fen_fd);
  1031. rc = copy_to_user(req_list_header->sync.rel_fen_fd,
  1032. &req->cur_rel_fen_fd, sizeof(int));
  1033. if (rc) {
  1034. pr_err("%s:copy_to_user failed\n", __func__);
  1035. goto parse_err_2;
  1036. }
  1037. } else {
  1038. fence = req->cur_rel_fence;
  1039. }
  1040. mdp3_ppp_req_push(req_q, req);
  1041. mutex_unlock(&ppp_stat->req_mutex);
  1042. schedule_work(&ppp_stat->blit_work);
  1043. if (!async) {
  1044. /* wait for release fence */
  1045. rc = sync_fence_wait(fence,
  1046. 5 * MSEC_PER_SEC);
  1047. if (rc < 0)
  1048. pr_err("%s: sync blit! rc = %x\n", __func__, rc);
  1049. sync_fence_put(fence);
  1050. fence = NULL;
  1051. }
  1052. return 0;
  1053. parse_err_2:
  1054. put_unused_fd(req->cur_rel_fen_fd);
  1055. parse_err_1:
  1056. for (i--; i >= 0; i--) {
  1057. mdp3_put_img(&req->src_data[i], MDP3_CLIENT_PPP);
  1058. mdp3_put_img(&req->dst_data[i], MDP3_CLIENT_PPP);
  1059. }
  1060. mdp3_ppp_deinit_buf_sync(req);
  1061. mutex_unlock(&ppp_stat->req_mutex);
  1062. return rc;
  1063. }
  1064. int mdp3_ppp_res_init(struct msm_fb_data_type *mfd)
  1065. {
  1066. const char timeline_name[] = "mdp3_ppp";
  1067. ppp_stat = kzalloc(sizeof(struct ppp_status), GFP_KERNEL);
  1068. if (!ppp_stat) {
  1069. pr_err("%s: kmalloc failed\n", __func__);
  1070. return -ENOMEM;
  1071. }
  1072. /*Setup sync_pt timeline for ppp*/
  1073. ppp_stat->timeline = sw_sync_timeline_create(timeline_name);
  1074. if (ppp_stat->timeline == NULL) {
  1075. pr_err("%s: cannot create time line\n", __func__);
  1076. return -ENOMEM;
  1077. } else {
  1078. ppp_stat->timeline_value = 1;
  1079. }
  1080. INIT_WORK(&ppp_stat->blit_work, mdp3_ppp_blit_wq_handler);
  1081. INIT_WORK(&ppp_stat->free_bw_work, mdp3_free_bw_wq_handler);
  1082. init_completion(&ppp_stat->pop_q_comp);
  1083. mutex_init(&ppp_stat->req_mutex);
  1084. mutex_init(&ppp_stat->config_ppp_mutex);
  1085. init_timer(&ppp_stat->free_bw_timer);
  1086. ppp_stat->free_bw_timer.function = mdp3_free_fw_timer_func;
  1087. ppp_stat->free_bw_timer.data = 0;
  1088. ppp_stat->mfd = mfd;
  1089. mdp3_ppp_callback_setup();
  1090. return 0;
  1091. }