mdp4_overlay_dtv.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261
  1. /* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. */
  13. #include <linux/module.h>
  14. #include <linux/kernel.h>
  15. #include <linux/sched.h>
  16. #include <linux/time.h>
  17. #include <linux/init.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/hrtimer.h>
  20. #include <linux/delay.h>
  21. #include <linux/io.h>
  22. #include <linux/semaphore.h>
  23. #include <linux/spinlock.h>
  24. #include <linux/fb.h>
  25. #include <asm/system.h>
  26. #include <asm/mach-types.h>
  27. #include <mach/hardware.h>
  28. #include "mdp.h"
  29. #include "msm_fb.h"
  30. #include "hdmi_msm.h"
  31. #include "mdp4.h"
  32. #define DTV_BASE 0xD0000
  33. static int dtv_enabled;
  34. /*#define DEBUG*/
  35. #ifdef DEBUG
  36. static void __mdp_outp(uint32 port, uint32 value)
  37. {
  38. uint32 in_val;
  39. outpdw(port, value);
  40. in_val = inpdw(port);
  41. printk(KERN_INFO "MDP-DTV[%04x] => %08x [%08x]\n",
  42. port-(uint32)(MDP_BASE + DTV_BASE), value, in_val);
  43. }
  44. #undef MDP_OUTP
  45. #define MDP_OUTP(port, value) __mdp_outp((uint32)(port), (value))
  46. #endif
  47. static int first_pixel_start_x;
  48. static int first_pixel_start_y;
  49. #define MAX_CONTROLLER 1
  50. static struct vsycn_ctrl {
  51. struct device *dev;
  52. int inited;
  53. int update_ndx;
  54. int dmae_intr_cnt;
  55. atomic_t suspend;
  56. atomic_t vsync_resume;
  57. int dmae_wait_cnt;
  58. int wait_vsync_cnt;
  59. int blt_change;
  60. int blt_ctrl;
  61. int blt_mode;
  62. int blt_free;
  63. int sysfs_created;
  64. struct mutex update_lock;
  65. struct completion ov_comp;
  66. struct completion dmae_comp;
  67. struct completion vsync_comp;
  68. spinlock_t spin_lock;
  69. struct msm_fb_data_type *mfd;
  70. struct mdp4_overlay_pipe *base_pipe;
  71. struct vsync_update vlist[2];
  72. int vsync_irq_enabled;
  73. ktime_t vsync_time;
  74. uint32 *avtimer;
  75. int vg1fd;
  76. int vg2fd;
  77. unsigned long long avtimer_tick;
  78. } vsync_ctrl_db[MAX_CONTROLLER];
  79. static void vsync_irq_enable(int intr, int term)
  80. {
  81. unsigned long flag;
  82. spin_lock_irqsave(&mdp_spin_lock, flag);
  83. outp32(MDP_INTR_CLEAR, intr);
  84. mdp_intr_mask |= intr;
  85. outp32(MDP_INTR_ENABLE, mdp_intr_mask);
  86. mdp_enable_irq(term);
  87. spin_unlock_irqrestore(&mdp_spin_lock, flag);
  88. pr_debug("%s: IRQ-en done, term=%x\n", __func__, term);
  89. }
  90. static void vsync_irq_disable(int intr, int term)
  91. {
  92. unsigned long flag;
  93. spin_lock_irqsave(&mdp_spin_lock, flag);
  94. outp32(MDP_INTR_CLEAR, intr);
  95. mdp_intr_mask &= ~intr;
  96. outp32(MDP_INTR_ENABLE, mdp_intr_mask);
  97. mdp_disable_irq_nosync(term);
  98. spin_unlock_irqrestore(&mdp_spin_lock, flag);
  99. pr_debug("%s: IRQ-dis done, term=%x\n", __func__, term);
  100. }
  101. void mdp4_overlay_dtv_start(void)
  102. {
  103. if (!dtv_enabled) {
  104. /* enable DTV block */
  105. mdp4_iommu_attach();
  106. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
  107. MDP_OUTP(MDP_BASE + DTV_BASE, 1);
  108. mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
  109. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
  110. dtv_enabled = 1;
  111. }
  112. }
  113. /*
  114. * mdp4_dtv_vsync_do_update:
  115. * called from thread context
  116. */
  117. void mdp4_dtv_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe)
  118. {
  119. struct vsycn_ctrl *vctrl;
  120. struct vsync_update *vp;
  121. struct mdp4_overlay_pipe *pp;
  122. int undx;
  123. if (cndx >= MAX_CONTROLLER) {
  124. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  125. return;
  126. }
  127. vctrl = &vsync_ctrl_db[cndx];
  128. if (atomic_read(&vctrl->suspend) > 0)
  129. return;
  130. mutex_lock(&vctrl->update_lock);
  131. undx = vctrl->update_ndx;
  132. vp = &vctrl->vlist[undx];
  133. pp = &vp->plist[pipe->pipe_ndx - 1]; /* ndx start form 1 */
  134. pr_debug("%s: vndx=%d pipe_ndx=%d flags=%x pid=%d\n",
  135. __func__, undx, pipe->pipe_ndx, pipe->flags, current->pid);
  136. *pp = *pipe; /* clone it */
  137. vp->update_cnt++;
  138. mutex_unlock(&vctrl->update_lock);
  139. mdp4_stat.overlay_play[pipe->mixer_num]++;
  140. }
  141. static void mdp4_dtv_blt_ov_update(struct mdp4_overlay_pipe *pipe);
  142. static void mdp4_dtv_wait4ov(int cndx);
  143. static void mdp4_dtv_wait4dmae(int cndx);
  144. int mdp4_dtv_pipe_commit(int cndx, int wait)
  145. {
  146. int i, undx;
  147. int mixer = 0;
  148. struct vsycn_ctrl *vctrl;
  149. struct vsync_update *vp;
  150. struct mdp4_overlay_pipe *pipe;
  151. struct mdp4_overlay_pipe *real_pipe;
  152. unsigned long flags;
  153. int cnt = 0;
  154. vctrl = &vsync_ctrl_db[cndx];
  155. mutex_lock(&vctrl->update_lock);
  156. undx = vctrl->update_ndx;
  157. vp = &vctrl->vlist[undx];
  158. pipe = vctrl->base_pipe;
  159. mixer = pipe->mixer_num;
  160. mdp4_overlay_iommu_unmap_freelist(mixer);
  161. mdp_update_pm(vctrl->mfd, vctrl->vsync_time);
  162. if (vp->update_cnt == 0) {
  163. mutex_unlock(&vctrl->update_lock);
  164. return 0;
  165. }
  166. vctrl->update_ndx++;
  167. vctrl->update_ndx &= 0x01;
  168. vp->update_cnt = 0; /* reset */
  169. if (vctrl->blt_free) {
  170. vctrl->blt_free--;
  171. if (vctrl->blt_free == 0)
  172. mdp4_free_writeback_buf(vctrl->mfd, mixer);
  173. }
  174. mutex_unlock(&vctrl->update_lock);
  175. pipe = vp->plist;
  176. for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
  177. if (pipe->pipe_used) {
  178. cnt++;
  179. real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
  180. if (real_pipe && real_pipe->pipe_used) {
  181. /* pipe not unset */
  182. mdp4_overlay_vsync_commit(pipe);
  183. }
  184. /* free previous iommu to freelist
  185. * which will be freed at next
  186. * pipe_commit
  187. */
  188. mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
  189. pipe->pipe_used = 0; /* clear */
  190. }
  191. }
  192. mdp4_mixer_stage_commit(mixer);
  193. /* start timing generator & mmu if they are not started yet */
  194. mdp4_overlay_dtv_start();
  195. pipe = vctrl->base_pipe;
  196. spin_lock_irqsave(&vctrl->spin_lock, flags);
  197. if (pipe->ov_blt_addr) {
  198. mdp4_dtv_blt_ov_update(pipe);
  199. pipe->blt_ov_done++;
  200. INIT_COMPLETION(vctrl->ov_comp);
  201. vsync_irq_enable(INTR_OVERLAY1_DONE, MDP_OVERLAY1_TERM);
  202. mb();
  203. pipe->blt_ov_koff++;
  204. /* kickoff overlay1 engine */
  205. mdp4_stat.kickoff_ov1++;
  206. outpdw(MDP_BASE + 0x0008, 0);
  207. } else {
  208. /* schedule second phase update at dmap */
  209. INIT_COMPLETION(vctrl->dmae_comp);
  210. vsync_irq_enable(INTR_DMA_E_DONE, MDP_DMA_E_TERM);
  211. }
  212. spin_unlock_irqrestore(&vctrl->spin_lock, flags);
  213. mdp4_stat.overlay_commit[pipe->mixer_num]++;
  214. if (wait) {
  215. if (pipe->ov_blt_addr)
  216. mdp4_dtv_wait4ov(cndx);
  217. else
  218. mdp4_dtv_wait4dmae(cndx);
  219. }
  220. return cnt;
  221. }
  222. void mdp4_dtv_vsync_ctrl(struct fb_info *info, int enable)
  223. {
  224. struct vsycn_ctrl *vctrl;
  225. int cndx = 0;
  226. vctrl = &vsync_ctrl_db[cndx];
  227. if (!external_common_state->hpd_state)
  228. complete_all(&vctrl->vsync_comp);
  229. if (vctrl->vsync_irq_enabled == enable)
  230. return;
  231. pr_debug("%s: vsync enable=%d\n", __func__, enable);
  232. vctrl->vsync_irq_enabled = enable;
  233. if (enable)
  234. vsync_irq_enable(INTR_EXTERNAL_VSYNC, MDP_EXTER_VSYNC_TERM);
  235. else
  236. vsync_irq_disable(INTR_EXTERNAL_VSYNC, MDP_EXTER_VSYNC_TERM);
  237. if (vctrl->vsync_irq_enabled && atomic_read(&vctrl->suspend) == 0)
  238. atomic_set(&vctrl->vsync_resume, 1);
  239. }
  240. void mdp4_dtv_wait4vsync(int cndx, long long *vtime)
  241. {
  242. struct vsycn_ctrl *vctrl;
  243. struct mdp4_overlay_pipe *pipe;
  244. unsigned long flags;
  245. if (cndx >= MAX_CONTROLLER) {
  246. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  247. return;
  248. }
  249. vctrl = &vsync_ctrl_db[cndx];
  250. pipe = vctrl->base_pipe;
  251. if (atomic_read(&vctrl->suspend) > 0)
  252. return;
  253. spin_lock_irqsave(&vctrl->spin_lock, flags);
  254. if (vctrl->wait_vsync_cnt == 0)
  255. INIT_COMPLETION(vctrl->vsync_comp);
  256. vctrl->wait_vsync_cnt++;
  257. spin_unlock_irqrestore(&vctrl->spin_lock, flags);
  258. wait_for_completion(&vctrl->vsync_comp);
  259. mdp4_stat.wait4vsync1++;
  260. *vtime = ktime_to_ns(vctrl->vsync_time);
  261. }
  262. static void mdp4_dtv_wait4ov(int cndx)
  263. {
  264. struct vsycn_ctrl *vctrl;
  265. if (cndx >= MAX_CONTROLLER) {
  266. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  267. return;
  268. }
  269. vctrl = &vsync_ctrl_db[cndx];
  270. if (atomic_read(&vctrl->suspend) > 0)
  271. return;
  272. wait_for_completion(&vctrl->ov_comp);
  273. }
  274. static void mdp4_dtv_wait4dmae(int cndx)
  275. {
  276. struct vsycn_ctrl *vctrl;
  277. if (cndx >= MAX_CONTROLLER) {
  278. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  279. return;
  280. }
  281. vctrl = &vsync_ctrl_db[cndx];
  282. if (atomic_read(&vctrl->suspend) > 0)
  283. return;
  284. wait_for_completion(&vctrl->dmae_comp);
  285. }
  286. ssize_t mdp4_dtv_show_event(struct device *dev,
  287. struct device_attribute *attr, char *buf)
  288. {
  289. int cndx;
  290. struct vsycn_ctrl *vctrl;
  291. ssize_t ret = 0;
  292. unsigned long flags;
  293. char ch = '\0';
  294. int vg1fd = -1, vg2fd = -1;
  295. unsigned long long avtimer_tick = 0;
  296. u64 vsync_tick = 0;
  297. cndx = 0;
  298. vctrl = &vsync_ctrl_db[0];
  299. memset(buf, 0, 64);
  300. if (atomic_read(&vctrl->suspend) > 0 ||
  301. !external_common_state->hpd_state ||
  302. atomic_read(&vctrl->vsync_resume) == 0)
  303. return 0;
  304. spin_lock_irqsave(&vctrl->spin_lock, flags);
  305. if (vctrl->wait_vsync_cnt == 0)
  306. INIT_COMPLETION(vctrl->vsync_comp);
  307. vctrl->wait_vsync_cnt++;
  308. spin_unlock_irqrestore(&vctrl->spin_lock, flags);
  309. ret = wait_for_completion_interruptible_timeout(&vctrl->vsync_comp,
  310. msecs_to_jiffies(VSYNC_PERIOD * 4));
  311. if (ret <= 0) {
  312. vctrl->wait_vsync_cnt = 0;
  313. vsync_tick = ktime_to_ns(ktime_get());
  314. ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
  315. buf[strlen(buf) + 1] = '\0';
  316. return ret;
  317. }
  318. spin_lock_irqsave(&vctrl->spin_lock, flags);
  319. vg1fd = vctrl->vg1fd;
  320. vg2fd = vctrl->vg2fd;
  321. avtimer_tick = vctrl->avtimer_tick;
  322. vsync_tick = ktime_to_ns(vctrl->vsync_time);
  323. spin_unlock_irqrestore(&vctrl->spin_lock, flags);
  324. ret = snprintf(buf, PAGE_SIZE,
  325. "VSYNC=%llu%c"
  326. "AVSYNCTP=%llu%c"
  327. "VG1MEMID=%d%c"
  328. "VG2MEMID=%d",
  329. vsync_tick,
  330. ch, avtimer_tick,
  331. ch, vg1fd,
  332. ch, vg2fd);
  333. return ret;
  334. }
  335. static void mdp4_dtv_wait4dmae_done(int cndx)
  336. {
  337. unsigned long flags;
  338. struct vsycn_ctrl *vctrl;
  339. if (cndx >= MAX_CONTROLLER) {
  340. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  341. return;
  342. }
  343. vctrl = &vsync_ctrl_db[cndx];
  344. if (atomic_read(&vctrl->suspend) > 0)
  345. return;
  346. spin_lock_irqsave(&vctrl->spin_lock, flags);
  347. INIT_COMPLETION(vctrl->dmae_comp);
  348. vsync_irq_enable(INTR_DMA_E_DONE, MDP_DMA_E_TERM);
  349. spin_unlock_irqrestore(&vctrl->spin_lock, flags);
  350. mdp4_dtv_wait4dmae(cndx);
  351. }
  352. void mdp4_dtv_vsync_init(int cndx)
  353. {
  354. struct vsycn_ctrl *vctrl;
  355. if (cndx >= MAX_CONTROLLER) {
  356. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  357. return;
  358. }
  359. pr_info("%s: ndx=%d\n", __func__, cndx);
  360. vctrl = &vsync_ctrl_db[cndx];
  361. if (vctrl->inited)
  362. return;
  363. vctrl->inited = 1;
  364. vctrl->update_ndx = 0;
  365. mutex_init(&vctrl->update_lock);
  366. init_completion(&vctrl->vsync_comp);
  367. init_completion(&vctrl->ov_comp);
  368. init_completion(&vctrl->dmae_comp);
  369. atomic_set(&vctrl->suspend, 1);
  370. atomic_set(&vctrl->vsync_resume, 1);
  371. spin_lock_init(&vctrl->spin_lock);
  372. }
  373. void mdp4_dtv_base_swap(int cndx, struct mdp4_overlay_pipe *pipe)
  374. {
  375. struct vsycn_ctrl *vctrl;
  376. if (!hdmi_prim_display) {
  377. pr_err("%s: failed, hdmi is not primary\n", __func__);
  378. return;
  379. }
  380. if (cndx >= MAX_CONTROLLER) {
  381. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  382. return;
  383. }
  384. vctrl = &vsync_ctrl_db[cndx];
  385. vctrl->base_pipe = pipe;
  386. }
  387. static int mdp4_dtv_start(struct msm_fb_data_type *mfd)
  388. {
  389. int dtv_width;
  390. int dtv_height;
  391. int dtv_bpp;
  392. int dtv_border_clr;
  393. int dtv_underflow_clr;
  394. int dtv_hsync_skew;
  395. int hsync_period;
  396. int hsync_ctrl;
  397. int vsync_period;
  398. int display_hctl;
  399. int display_v_start;
  400. int display_v_end;
  401. int active_hctl;
  402. int active_h_start;
  403. int active_h_end;
  404. int active_v_start;
  405. int active_v_end;
  406. int ctrl_polarity;
  407. int h_back_porch;
  408. int h_front_porch;
  409. int v_back_porch;
  410. int v_front_porch;
  411. int hsync_pulse_width;
  412. int vsync_pulse_width;
  413. int hsync_polarity;
  414. int vsync_polarity;
  415. int data_en_polarity;
  416. int hsync_start_x;
  417. int hsync_end_x;
  418. struct fb_info *fbi;
  419. struct fb_var_screeninfo *var;
  420. struct vsycn_ctrl *vctrl;
  421. vctrl = &vsync_ctrl_db[0];
  422. if (!mfd)
  423. return -ENODEV;
  424. if (mfd->key != MFD_KEY)
  425. return -EINVAL;
  426. fbi = mfd->fbi;
  427. var = &fbi->var;
  428. vctrl->mfd = mfd;
  429. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
  430. if (hdmi_prim_display) {
  431. if (is_mdp4_hw_reset()) {
  432. mdp4_hw_init();
  433. outpdw(MDP_BASE + 0x0038, mdp4_display_intf);
  434. }
  435. }
  436. mdp4_overlay_dmae_cfg(mfd, 0);
  437. /*
  438. * DTV timing setting
  439. */
  440. h_back_porch = var->left_margin;
  441. h_front_porch = var->right_margin;
  442. v_back_porch = var->upper_margin;
  443. v_front_porch = var->lower_margin;
  444. hsync_pulse_width = var->hsync_len;
  445. vsync_pulse_width = var->vsync_len;
  446. dtv_border_clr = mfd->panel_info.lcdc.border_clr;
  447. dtv_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
  448. dtv_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
  449. pr_info("%s: <ID=%d %dx%d (%d,%d,%d), (%d,%d,%d) %dMHz>\n", __func__,
  450. var->reserved[3], var->xres, var->yres,
  451. var->right_margin, var->hsync_len, var->left_margin,
  452. var->lower_margin, var->vsync_len, var->upper_margin,
  453. var->pixclock/1000/1000);
  454. dtv_width = var->xres;
  455. dtv_height = var->yres;
  456. dtv_bpp = mfd->panel_info.bpp;
  457. hsync_period =
  458. hsync_pulse_width + h_back_porch + dtv_width + h_front_porch;
  459. hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
  460. hsync_start_x = hsync_pulse_width + h_back_porch;
  461. hsync_end_x = hsync_period - h_front_porch - 1;
  462. display_hctl = (hsync_end_x << 16) | hsync_start_x;
  463. vsync_period =
  464. (vsync_pulse_width + v_back_porch + dtv_height +
  465. v_front_porch) * hsync_period;
  466. display_v_start =
  467. (vsync_pulse_width + v_back_porch) * hsync_period + dtv_hsync_skew;
  468. display_v_end =
  469. vsync_period - (v_front_porch * hsync_period) + dtv_hsync_skew - 1;
  470. if (dtv_width != var->xres) {
  471. active_h_start = hsync_start_x + first_pixel_start_x;
  472. active_h_end = active_h_start + var->xres - 1;
  473. active_hctl =
  474. ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
  475. } else {
  476. active_hctl = 0;
  477. }
  478. if (dtv_height != var->yres) {
  479. active_v_start =
  480. display_v_start + first_pixel_start_y * hsync_period;
  481. active_v_end = active_v_start + (var->yres) * hsync_period - 1;
  482. active_v_start |= ACTIVE_START_Y_EN;
  483. } else {
  484. active_v_start = 0;
  485. active_v_end = 0;
  486. }
  487. dtv_underflow_clr |= 0x80000000; /* enable recovery */
  488. hsync_polarity = fbi->var.yres >= 720 ? 0 : 1;
  489. vsync_polarity = fbi->var.yres >= 720 ? 0 : 1;
  490. data_en_polarity = 0;
  491. ctrl_polarity =
  492. (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
  493. MDP_OUTP(MDP_BASE + DTV_BASE + 0x4, hsync_ctrl);
  494. MDP_OUTP(MDP_BASE + DTV_BASE + 0x8, vsync_period);
  495. MDP_OUTP(MDP_BASE + DTV_BASE + 0xc, vsync_pulse_width * hsync_period);
  496. MDP_OUTP(MDP_BASE + DTV_BASE + 0x18, display_hctl);
  497. MDP_OUTP(MDP_BASE + DTV_BASE + 0x1c, display_v_start);
  498. MDP_OUTP(MDP_BASE + DTV_BASE + 0x20, display_v_end);
  499. MDP_OUTP(MDP_BASE + DTV_BASE + 0x40, dtv_border_clr);
  500. MDP_OUTP(MDP_BASE + DTV_BASE + 0x44, dtv_underflow_clr);
  501. MDP_OUTP(MDP_BASE + DTV_BASE + 0x48, dtv_hsync_skew);
  502. MDP_OUTP(MDP_BASE + DTV_BASE + 0x50, ctrl_polarity);
  503. MDP_OUTP(MDP_BASE + DTV_BASE + 0x2c, active_hctl);
  504. MDP_OUTP(MDP_BASE + DTV_BASE + 0x30, active_v_start);
  505. MDP_OUTP(MDP_BASE + DTV_BASE + 0x38, active_v_end);
  506. /* Test pattern 8 x 8 pixel */
  507. /* MDP_OUTP(MDP_BASE + DTV_BASE + 0x4C, 0x80000808); */
  508. /* enable DTV block */
  509. MDP_OUTP(MDP_BASE + DTV_BASE, 1);
  510. dtv_enabled = 1;
  511. return 0;
  512. }
  513. static int mdp4_dtv_stop(struct msm_fb_data_type *mfd)
  514. {
  515. int cndx = 0;
  516. struct vsycn_ctrl *vctrl;
  517. vctrl = &vsync_ctrl_db[cndx];
  518. if (vctrl->base_pipe == NULL)
  519. return -EINVAL;
  520. MDP_OUTP(MDP_BASE + DTV_BASE, 0);
  521. dtv_enabled = 0;
  522. return 0;
  523. }
  524. int mdp4_dtv_on(struct platform_device *pdev)
  525. {
  526. struct msm_fb_data_type *mfd;
  527. int ret = 0;
  528. int cndx = 0;
  529. struct vsycn_ctrl *vctrl;
  530. struct msm_panel_info *pinfo;
  531. vctrl = &vsync_ctrl_db[cndx];
  532. mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
  533. if (!mfd)
  534. return -ENODEV;
  535. if (mfd->key != MFD_KEY)
  536. return -EINVAL;
  537. vctrl->mfd = mfd;
  538. vctrl->dev = mfd->fbi->dev;
  539. pinfo = &mfd->panel_info;
  540. vctrl->blt_ctrl = pinfo->lcd.blt_ctrl;
  541. vctrl->blt_mode = pinfo->lcd.blt_mode;
  542. mdp_footswitch_ctrl(TRUE);
  543. /* Mdp clock enable */
  544. mdp_clk_ctrl(1);
  545. mdp4_overlay_panel_mode(MDP4_MIXER1, MDP4_PANEL_DTV);
  546. /* Allocate dtv_pipe at dtv_on*/
  547. if (vctrl->base_pipe == NULL) {
  548. if (mdp4_overlay_dtv_set(mfd, NULL)) {
  549. pr_warn("%s: dtv_pipe is NULL, dtv_set failed\n",
  550. __func__);
  551. return -EINVAL;
  552. }
  553. }
  554. ret = panel_next_on(pdev);
  555. if (ret != 0)
  556. pr_warn("%s: panel_next_on failed", __func__);
  557. atomic_set(&vctrl->suspend, 0);
  558. if (mfd->avtimer_phy && (vctrl->avtimer == NULL)) {
  559. vctrl->avtimer = (uint32 *)ioremap(mfd->avtimer_phy, 8);
  560. if (vctrl->avtimer == NULL)
  561. pr_err(" avtimer ioremap fail\n");
  562. }
  563. pr_info("%s:\n", __func__);
  564. return ret;
  565. }
  566. int mdp4_dtv_off(struct platform_device *pdev)
  567. {
  568. struct msm_fb_data_type *mfd;
  569. int ret = 0;
  570. int cndx = 0;
  571. int undx;
  572. struct vsycn_ctrl *vctrl;
  573. struct mdp4_overlay_pipe *pipe;
  574. struct vsync_update *vp;
  575. mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
  576. vctrl = &vsync_ctrl_db[cndx];
  577. atomic_set(&vctrl->suspend, 1);
  578. atomic_set(&vctrl->vsync_resume, 0);
  579. /* wait for one vsycn time to make sure
  580. * previous stage_commit had been kicked in
  581. */
  582. msleep(20); /* >= 17 ms */
  583. complete_all(&vctrl->vsync_comp);
  584. pipe = vctrl->base_pipe;
  585. if (pipe != NULL) {
  586. mdp4_dtv_stop(mfd);
  587. /* sanity check, free pipes besides base layer */
  588. mdp4_overlay_unset_mixer(pipe->mixer_num);
  589. if (hdmi_prim_display && mfd->ref_cnt == 0) {
  590. /* adb stop */
  591. if (pipe->pipe_type == OVERLAY_TYPE_BF)
  592. mdp4_overlay_borderfill_stage_down(pipe);
  593. /* base pipe may change after borderfill_stage_down */
  594. pipe = vctrl->base_pipe;
  595. mdp4_mixer_stage_down(pipe, 1);
  596. mdp4_overlay_pipe_free(pipe);
  597. /* pipe == rgb2 */
  598. vctrl->base_pipe = NULL;
  599. } else {
  600. mdp4_mixer_stage_down(pipe, 1);
  601. mdp4_overlay_pipe_free(pipe);
  602. vctrl->base_pipe = NULL;
  603. }
  604. }
  605. mdp4_overlay_panel_mode_unset(MDP4_MIXER1, MDP4_PANEL_DTV);
  606. if (vctrl->vsync_irq_enabled) {
  607. vctrl->vsync_irq_enabled = 0;
  608. vsync_irq_disable(INTR_EXTERNAL_VSYNC, MDP_EXTER_VSYNC_TERM);
  609. }
  610. undx = vctrl->update_ndx;
  611. vp = &vctrl->vlist[undx];
  612. if (vp->update_cnt) {
  613. /*
  614. * pipe's iommu will be freed at next overlay play
  615. * and iommu_drop statistic will be increased by one
  616. */
  617. vp->update_cnt = 0; /* empty queue */
  618. }
  619. if (vctrl->avtimer != NULL) {
  620. iounmap(vctrl->avtimer);
  621. vctrl->avtimer = NULL;
  622. }
  623. ret = panel_next_off(pdev);
  624. mdp_footswitch_ctrl(FALSE);
  625. /* Mdp clock disable */
  626. mdp_clk_ctrl(0);
  627. pr_info("%s:\n", __func__);
  628. return ret;
  629. }
  630. static void mdp4_dtv_blt_ov_update(struct mdp4_overlay_pipe *pipe)
  631. {
  632. uint32 off, addr;
  633. int bpp;
  634. char *overlay_base;
  635. if (pipe->ov_blt_addr == 0)
  636. return;
  637. #ifdef BLT_RGB565
  638. bpp = 2; /* overlay ouput is RGB565 */
  639. #else
  640. bpp = 3; /* overlay ouput is RGB888 */
  641. #endif
  642. off = 0;
  643. if (pipe->blt_ov_done & 0x01)
  644. off = pipe->src_height * pipe->src_width * bpp;
  645. addr = pipe->ov_blt_addr + off;
  646. /* overlay 1 */
  647. overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x10000 */
  648. outpdw(overlay_base + 0x000c, addr);
  649. outpdw(overlay_base + 0x001c, addr);
  650. }
  651. static void mdp4_dtv_blt_dmae_update(struct mdp4_overlay_pipe *pipe)
  652. {
  653. uint32 off, addr;
  654. int bpp;
  655. if (pipe->ov_blt_addr == 0)
  656. return;
  657. #ifdef BLT_RGB565
  658. bpp = 2; /* overlay ouput is RGB565 */
  659. #else
  660. bpp = 3; /* overlay ouput is RGB888 */
  661. #endif
  662. off = 0;
  663. if (pipe->blt_dmap_done & 0x01)
  664. off = pipe->src_height * pipe->src_width * bpp;
  665. addr = pipe->dma_blt_addr + off;
  666. /* dmae */
  667. MDP_OUTP(MDP_BASE + 0xb0008, addr);
  668. }
  669. static void mdp4_overlay_dtv_alloc_pipe(struct msm_fb_data_type *mfd,
  670. int32 ptype, struct vsycn_ctrl *vctrl)
  671. {
  672. int ret = 0;
  673. struct fb_info *fbi = mfd->fbi;
  674. struct mdp4_overlay_pipe *pipe;
  675. if (vctrl->base_pipe != NULL)
  676. return;
  677. pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER1);
  678. if (pipe == NULL) {
  679. pr_err("%s: pipe_alloc failed\n", __func__);
  680. return;
  681. }
  682. pipe->pipe_used++;
  683. pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
  684. pipe->mixer_num = MDP4_MIXER1;
  685. if (ptype == OVERLAY_TYPE_BF) {
  686. /* LSP_BORDER_COLOR */
  687. MDP_OUTP(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x5004,
  688. ((0x0 & 0xFFF) << 16) | /* 12-bit B */
  689. (0x0 & 0xFFF)); /* 12-bit G */
  690. /* MSP_BORDER_COLOR */
  691. MDP_OUTP(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x5008,
  692. (0x0 & 0xFFF)); /* 12-bit R */
  693. pipe->src_format = MDP_ARGB_8888;
  694. } else {
  695. switch (mfd->ibuf.bpp) {
  696. case 2:
  697. pipe->src_format = MDP_RGB_565;
  698. break;
  699. case 3:
  700. pipe->src_format = MDP_RGB_888;
  701. break;
  702. case 4:
  703. default:
  704. if (hdmi_prim_display)
  705. pipe->src_format = MSMFB_DEFAULT_TYPE;
  706. else
  707. pipe->src_format = MDP_ARGB_8888;
  708. break;
  709. }
  710. }
  711. pipe->src_height = fbi->var.yres;
  712. pipe->src_width = fbi->var.xres;
  713. pipe->src_h = fbi->var.yres;
  714. pipe->src_w = fbi->var.xres;
  715. pipe->dst_h = fbi->var.yres;
  716. pipe->dst_w = fbi->var.xres;
  717. pipe->src_y = 0;
  718. pipe->src_x = 0;
  719. pipe->dst_h = fbi->var.yres;
  720. pipe->dst_w = fbi->var.xres;
  721. pipe->srcp0_ystride = fbi->fix.line_length;
  722. mdp4_overlay_mdp_pipe_req(pipe, mfd);
  723. mdp4_calc_blt_mdp_bw(mfd, pipe);
  724. ret = mdp4_overlay_format2pipe(pipe);
  725. if (ret < 0)
  726. pr_warn("%s: format2type failed\n", __func__);
  727. mdp4_overlay_dmae_xy(pipe); /* dma_e */
  728. mdp4_overlayproc_cfg(pipe);
  729. if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
  730. pipe->srcp0_addr = (uint32) mfd->ibuf.buf;
  731. mdp4_overlay_rgb_setup(pipe);
  732. }
  733. mdp4_overlay_reg_flush(pipe, 1);
  734. mdp4_mixer_stage_up(pipe, 0);
  735. mdp4_mixer_stage_commit(pipe->mixer_num);
  736. vctrl->base_pipe = pipe; /* keep it */
  737. }
  738. int mdp4_overlay_dtv_set(struct msm_fb_data_type *mfd,
  739. struct mdp4_overlay_pipe *pipe)
  740. {
  741. int cndx = 0;
  742. struct vsycn_ctrl *vctrl;
  743. vctrl = &vsync_ctrl_db[cndx];
  744. if (vctrl->base_pipe != NULL)
  745. return 0;
  746. if (pipe != NULL && pipe->mixer_stage == MDP4_MIXER_STAGE_BASE &&
  747. pipe->pipe_type == OVERLAY_TYPE_RGB)
  748. vctrl->base_pipe = pipe; /* keep it */
  749. else if (!hdmi_prim_display && mdp4_overlay_borderfill_supported())
  750. mdp4_overlay_dtv_alloc_pipe(mfd, OVERLAY_TYPE_BF, vctrl);
  751. else
  752. mdp4_overlay_dtv_alloc_pipe(mfd, OVERLAY_TYPE_RGB, vctrl);
  753. if (vctrl->base_pipe == NULL)
  754. return -ENODEV;
  755. mdp4_init_writeback_buf(mfd, MDP4_MIXER1);
  756. vctrl->base_pipe->ov_blt_addr = 0;
  757. vctrl->base_pipe->dma_blt_addr = 0;
  758. return mdp4_dtv_start(mfd);
  759. }
  760. int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
  761. struct mdp4_overlay_pipe *pipe)
  762. {
  763. int result = 0;
  764. int cndx = 0;
  765. struct vsycn_ctrl *vctrl;
  766. vctrl = &vsync_ctrl_db[cndx];
  767. if (vctrl->base_pipe == NULL)
  768. return 0;
  769. if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE &&
  770. pipe->pipe_type == OVERLAY_TYPE_RGB) {
  771. result = mdp4_dtv_stop(mfd);
  772. vctrl->base_pipe = NULL;
  773. }
  774. if (pipe->pipe_num == OVERLAY_PIPE_VG1)
  775. vctrl->vg1fd = -1;
  776. else if (pipe->pipe_num == OVERLAY_PIPE_VG2)
  777. vctrl->vg2fd = -1;
  778. return result;
  779. }
  780. /* TODO: dtv writeback need to be added later */
  781. void mdp4_external_vsync_dtv(void)
  782. {
  783. int cndx;
  784. struct vsycn_ctrl *vctrl;
  785. uint32 *tp, LSW;
  786. cndx = 0;
  787. vctrl = &vsync_ctrl_db[cndx];
  788. pr_debug("%s: cpu=%d\n", __func__, smp_processor_id());
  789. spin_lock(&vctrl->spin_lock);
  790. vctrl->vsync_time = ktime_get();
  791. vctrl->avtimer_tick = 0;
  792. if (vctrl->avtimer && ((vctrl->vg1fd > 0) || (vctrl->vg2fd > 0))) {
  793. tp = vctrl->avtimer;
  794. LSW = inpdw(tp);
  795. tp++;
  796. vctrl->avtimer_tick = (unsigned long long) inpdw(tp);
  797. vctrl->avtimer_tick = ((vctrl->avtimer_tick << 32) | LSW);
  798. }
  799. if (vctrl->wait_vsync_cnt) {
  800. complete_all(&vctrl->vsync_comp);
  801. vctrl->wait_vsync_cnt = 0;
  802. }
  803. spin_unlock(&vctrl->spin_lock);
  804. }
  805. /*
  806. * mdp4_dmae_done_dtv: called from isr
  807. */
  808. void mdp4_dmae_done_dtv(void)
  809. {
  810. int cndx;
  811. struct vsycn_ctrl *vctrl;
  812. struct mdp4_overlay_pipe *pipe;
  813. cndx = 0;
  814. if (cndx >= MAX_CONTROLLER) {
  815. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  816. return;
  817. }
  818. vctrl = &vsync_ctrl_db[cndx];
  819. pipe = vctrl->base_pipe;
  820. if (pipe == NULL)
  821. return;
  822. pr_debug("%s: cpu=%d\n", __func__, smp_processor_id());
  823. spin_lock(&vctrl->spin_lock);
  824. if (vctrl->blt_change) {
  825. mdp4_overlayproc_cfg(pipe);
  826. mdp4_overlay_dmae_xy(pipe);
  827. vctrl->blt_change = 0;
  828. }
  829. if (mdp_rev <= MDP_REV_41)
  830. mdp4_mixer_blend_cfg(MDP4_MIXER1);
  831. complete_all(&vctrl->dmae_comp);
  832. mdp4_overlay_dma_commit(MDP4_MIXER1);
  833. vsync_irq_disable(INTR_DMA_E_DONE, MDP_DMA_E_TERM);
  834. spin_unlock(&vctrl->spin_lock);
  835. }
  836. /*
  837. * mdp4_overlay1_done_dtv: called from isr
  838. */
  839. void mdp4_overlay1_done_dtv(void)
  840. {
  841. struct vsycn_ctrl *vctrl;
  842. struct mdp4_overlay_pipe *pipe;
  843. int cndx = 0;
  844. vctrl = &vsync_ctrl_db[cndx];
  845. pipe = vctrl->base_pipe;
  846. if (pipe == NULL)
  847. return;
  848. spin_lock(&vctrl->spin_lock);
  849. if (pipe->ov_blt_addr == 0) {
  850. spin_unlock(&vctrl->spin_lock);
  851. return;
  852. }
  853. mdp4_dtv_blt_dmae_update(pipe);
  854. complete_all(&vctrl->ov_comp);
  855. pipe->blt_dmap_done++;
  856. vsync_irq_disable(INTR_OVERLAY1_DONE, MDP_OVERLAY1_TERM);
  857. spin_unlock(&vctrl->spin_lock);
  858. }
  859. void mdp4_dtv_set_black_screen()
  860. {
  861. char *rgb_base;
  862. /*Black color*/
  863. uint32 color = 0x00000000;
  864. uint32 temp_src_format;
  865. int commit = 1, cndx = 0;
  866. int pipe_num = OVERLAY_PIPE_RGB1;
  867. struct vsycn_ctrl *vctrl;
  868. vctrl = &vsync_ctrl_db[cndx];
  869. if (!hdmi_prim_display)
  870. return;
  871. if (vctrl->base_pipe == NULL)
  872. commit = 0;
  873. else
  874. pipe_num = vctrl->base_pipe->pipe_num;
  875. rgb_base = MDP_BASE;
  876. rgb_base += (MDP4_RGB_OFF * (pipe_num + 2));
  877. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
  878. /* RGB Constant Color */
  879. MDP_OUTP(rgb_base + 0x1008, color);
  880. /* MDP_RGB_SRC_FORMAT */
  881. temp_src_format = inpdw(rgb_base + 0x0050);
  882. MDP_OUTP(rgb_base + 0x0050, temp_src_format | BIT(22));
  883. if (commit) {
  884. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
  885. mdp4_overlay_reg_flush(vctrl->base_pipe, 1);
  886. mdp4_mixer_stage_up(vctrl->base_pipe, 0);
  887. mdp4_mixer_stage_commit(vctrl->base_pipe->mixer_num);
  888. } else {
  889. /* MDP_OVERLAY_REG_FLUSH for pipe*/
  890. MDP_OUTP(MDP_BASE + 0x18000,
  891. BIT(pipe_num + 2) | BIT(MDP4_MIXER1));
  892. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
  893. }
  894. }
  895. static void mdp4_dtv_do_blt(struct msm_fb_data_type *mfd, int enable)
  896. {
  897. unsigned long flag;
  898. int cndx = 0;
  899. struct vsycn_ctrl *vctrl;
  900. struct mdp4_overlay_pipe *pipe;
  901. u32 mode, ctrl;
  902. vctrl = &vsync_ctrl_db[cndx];
  903. pipe = vctrl->base_pipe;
  904. mode = (dbg_force_ov1_blt & 0x0f) ?
  905. (dbg_force_ov1_blt & 0x0f) : vctrl->blt_mode;
  906. ctrl = (dbg_force_ov1_blt >> 4) ?
  907. (dbg_force_ov1_blt >> 4) : vctrl->blt_ctrl;
  908. pr_debug("%s: mode=%d, ctrl = %d, enable=%d ov_blt_addr=%x\n",
  909. __func__, mode, ctrl, enable, (int)pipe->ov_blt_addr);
  910. if ((mode == MDP4_OVERLAY_MODE_BLT_ALWAYS_OFF) &&
  911. !pipe->ov_blt_addr)
  912. return;
  913. else if ((mode == MDP4_OVERLAY_MODE_BLT_ALWAYS_ON) &&
  914. pipe->ov_blt_addr)
  915. return;
  916. else if (enable && pipe->ov_blt_addr)
  917. return;
  918. else if (!enable && !pipe->ov_blt_addr)
  919. return;
  920. if (pipe->ov_blt_addr == 0) {
  921. mdp4_allocate_writeback_buf(vctrl->mfd, MDP4_MIXER1);
  922. if (!vctrl->mfd->ov1_wb_buf->write_addr) {
  923. pr_warning("%s: ctrl=%d blt_base NOT assigned\n",
  924. __func__, cndx);
  925. return;
  926. }
  927. }
  928. pr_debug("%s: mode=%d, ctrl=%d, enable=%d ov_blt_addr=%x\n",
  929. __func__, mode, ctrl, enable, (int)pipe->ov_blt_addr);
  930. spin_lock_irqsave(&vctrl->spin_lock, flag);
  931. if (enable && pipe->ov_blt_addr == 0) {
  932. pipe->ov_blt_addr = vctrl->mfd->ov1_wb_buf->write_addr;
  933. pipe->dma_blt_addr = vctrl->mfd->ov1_wb_buf->read_addr;
  934. pipe->blt_cnt = 0;
  935. pipe->ov_cnt = 0;
  936. pipe->blt_dmap_done = 0;
  937. pipe->blt_ov_koff = 0;
  938. pipe->blt_ov_done = 0;
  939. mdp4_stat.blt_dtv++;
  940. vctrl->blt_free = 0;
  941. } else if (enable == 0 && pipe->ov_blt_addr) {
  942. pipe->ov_blt_addr = 0;
  943. pipe->dma_blt_addr = 0;
  944. vctrl->blt_free = 4;
  945. }
  946. spin_unlock_irqrestore(&vctrl->spin_lock, flag);
  947. if (ctrl == MDP4_OVERLAY_BLT_SWITCH_TG_ON) {
  948. spin_lock_irqsave(&vctrl->spin_lock, flag);
  949. if (!dtv_enabled) {
  950. pr_debug("%s: blt switched not in isr dtv_enabled=%d\n",
  951. __func__, dtv_enabled);
  952. mdp4_overlayproc_cfg(pipe);
  953. mdp4_overlay_dmae_xy(pipe);
  954. } else {
  955. pr_debug("%s: blt switched in ISR dtv_enabled=%d\n",
  956. __func__, dtv_enabled);
  957. vctrl->blt_change++;
  958. }
  959. spin_unlock_irqrestore(&vctrl->spin_lock, flag);
  960. if (dtv_enabled)
  961. mdp4_dtv_wait4dmae_done(0);
  962. } else if (ctrl == MDP4_OVERLAY_BLT_SWITCH_TG_OFF) {
  963. pr_debug("%s: dtv blt switched by turning TG off\n",
  964. __func__);
  965. if (dtv_enabled) {
  966. mdp4_dtv_wait4dmae_done(0);
  967. MDP_OUTP(MDP_BASE + DTV_BASE, 0);
  968. msleep(20);
  969. }
  970. mdp4_overlayproc_cfg(pipe);
  971. mdp4_overlay_dmae_xy(pipe);
  972. if (dtv_enabled)
  973. MDP_OUTP(MDP_BASE + DTV_BASE, 1);
  974. } else if (ctrl == MDP4_OVERLAY_BLT_SWITCH_POLL) {
  975. pr_debug("%s: dtv blt change by polling status\n",
  976. __func__);
  977. while (inpdw(MDP_BASE + 0x0018) & 0x12)
  978. cpu_relax();
  979. mdp4_overlayproc_cfg(pipe);
  980. mdp4_overlay_dmae_xy(pipe);
  981. } else
  982. pr_err("%s: ctrl=%d is not supported\n", __func__, ctrl);
  983. }
  984. void mdp4_dtv_overlay_blt_start(struct msm_fb_data_type *mfd)
  985. {
  986. mdp4_dtv_do_blt(mfd, 1);
  987. }
  988. void mdp4_dtv_overlay_blt_stop(struct msm_fb_data_type *mfd)
  989. {
  990. mdp4_dtv_do_blt(mfd, 0);
  991. }
  992. void mdp4_dtv_overlay(struct msm_fb_data_type *mfd)
  993. {
  994. int cndx = 0;
  995. struct vsycn_ctrl *vctrl;
  996. struct mdp4_overlay_pipe *pipe;
  997. int wait = 0;
  998. mutex_lock(&mfd->dma->ov_mutex);
  999. if (!mfd->panel_power_on) {
  1000. mutex_unlock(&mfd->dma->ov_mutex);
  1001. return;
  1002. }
  1003. vctrl = &vsync_ctrl_db[cndx];
  1004. if (vctrl->base_pipe == NULL)
  1005. mdp4_overlay_dtv_set(mfd, NULL);
  1006. pipe = vctrl->base_pipe;
  1007. if (pipe == NULL) {
  1008. pr_warn("%s: dtv_pipe == NULL\n", __func__);
  1009. mutex_unlock(&mfd->dma->ov_mutex);
  1010. return;
  1011. }
  1012. if (hdmi_prim_display && (pipe->pipe_used == 0 ||
  1013. pipe->mixer_stage != MDP4_MIXER_STAGE_BASE)) {
  1014. pr_err("%s: NOT baselayer\n", __func__);
  1015. mutex_unlock(&mfd->dma->ov_mutex);
  1016. return;
  1017. }
  1018. if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
  1019. pipe->srcp0_addr = (uint32)mfd->ibuf.buf;
  1020. mdp4_dtv_pipe_queue(0, pipe);
  1021. }
  1022. if (hdmi_prim_display)
  1023. wait = 1;
  1024. mdp4_overlay_mdp_perf_upd(mfd, 1);
  1025. mdp4_dtv_pipe_commit(cndx, wait);
  1026. mdp4_overlay_mdp_perf_upd(mfd, 0);
  1027. mutex_unlock(&mfd->dma->ov_mutex);
  1028. }
  1029. void mdp4_dtv_set_avparams(struct mdp4_overlay_pipe *pipe, int id)
  1030. {
  1031. struct vsycn_ctrl *vctrl;
  1032. if (pipe == NULL) {
  1033. pr_warn("%s: dtv_pipe == NULL\n", __func__);
  1034. return;
  1035. }
  1036. vctrl = &vsync_ctrl_db[0];
  1037. if (pipe->pipe_num == OVERLAY_PIPE_VG1)
  1038. vctrl->vg1fd = id;
  1039. else if (pipe->pipe_num == OVERLAY_PIPE_VG2)
  1040. vctrl->vg2fd = id;
  1041. }