mdp4_overlay_dsi_video.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145
  1. /* Copyright (c) 2010-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 <linux/msm_mdp.h>
  26. #include <linux/ktime.h>
  27. #include <linux/wakelock.h>
  28. #include <linux/time.h>
  29. #include <asm/system.h>
  30. #include <asm/mach-types.h>
  31. #include <mach/hardware.h>
  32. #include "mdp.h"
  33. #include "msm_fb.h"
  34. #include "mdp4.h"
  35. #include "mipi_dsi.h"
  36. #include <mach/iommu_domains.h>
  37. #define DSI_VIDEO_BASE 0xE0000
  38. static int first_pixel_start_x;
  39. static int first_pixel_start_y;
  40. static int dsi_video_enabled;
  41. #define MAX_CONTROLLER 1
  42. static struct vsycn_ctrl {
  43. struct device *dev;
  44. int inited;
  45. int update_ndx;
  46. int ov_koff;
  47. int ov_done;
  48. atomic_t suspend;
  49. atomic_t vsync_resume;
  50. int wait_vsync_cnt;
  51. int blt_change;
  52. int blt_free;
  53. u32 blt_ctrl;
  54. u32 blt_mode;
  55. int sysfs_created;
  56. struct mutex update_lock;
  57. struct completion ov_comp;
  58. struct completion dmap_comp;
  59. struct completion vsync_comp;
  60. spinlock_t spin_lock;
  61. struct msm_fb_data_type *mfd;
  62. struct mdp4_overlay_pipe *base_pipe;
  63. struct vsync_update vlist[2];
  64. int vsync_irq_enabled;
  65. ktime_t vsync_time;
  66. } vsync_ctrl_db[MAX_CONTROLLER];
  67. static void vsync_irq_enable(int intr, int term)
  68. {
  69. unsigned long flag;
  70. spin_lock_irqsave(&mdp_spin_lock, flag);
  71. outp32(MDP_INTR_CLEAR, intr);
  72. mdp_intr_mask |= intr;
  73. outp32(MDP_INTR_ENABLE, mdp_intr_mask);
  74. mdp_enable_irq(term);
  75. spin_unlock_irqrestore(&mdp_spin_lock, flag);
  76. pr_debug("%s: IRQ-en done, term=%x\n", __func__, term);
  77. }
  78. static void vsync_irq_disable(int intr, int term)
  79. {
  80. unsigned long flag;
  81. spin_lock_irqsave(&mdp_spin_lock, flag);
  82. outp32(MDP_INTR_CLEAR, intr);
  83. mdp_intr_mask &= ~intr;
  84. outp32(MDP_INTR_ENABLE, mdp_intr_mask);
  85. mdp_disable_irq_nosync(term);
  86. spin_unlock_irqrestore(&mdp_spin_lock, flag);
  87. pr_debug("%s: IRQ-dis done, term=%x\n", __func__, term);
  88. }
  89. static void mdp4_overlay_dsi_video_start(void)
  90. {
  91. if (!dsi_video_enabled) {
  92. /* enable DSI block */
  93. mdp4_iommu_attach();
  94. mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
  95. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1);
  96. dsi_video_enabled = 1;
  97. }
  98. }
  99. /*
  100. * mdp4_dsi_video_pipe_queue:
  101. * called from thread context
  102. */
  103. void mdp4_dsi_video_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe)
  104. {
  105. struct vsycn_ctrl *vctrl;
  106. struct vsync_update *vp;
  107. struct mdp4_overlay_pipe *pp;
  108. int undx;
  109. if (cndx >= MAX_CONTROLLER) {
  110. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  111. return;
  112. }
  113. vctrl = &vsync_ctrl_db[cndx];
  114. if (atomic_read(&vctrl->suspend) > 0)
  115. return;
  116. mutex_lock(&vctrl->update_lock);
  117. undx = vctrl->update_ndx;
  118. vp = &vctrl->vlist[undx];
  119. pp = &vp->plist[pipe->pipe_ndx - 1]; /* ndx start form 1 */
  120. pr_debug("%s: vndx=%d pipe=%x ndx=%d num=%d pid=%d\n",
  121. __func__, undx, (int)pipe, pipe->pipe_ndx, pipe->pipe_num,
  122. current->pid);
  123. *pp = *pipe; /* clone it */
  124. vp->update_cnt++;
  125. mutex_unlock(&vctrl->update_lock);
  126. mdp4_stat.overlay_play[pipe->mixer_num]++;
  127. }
  128. static void mdp4_dsi_video_blt_ov_update(struct mdp4_overlay_pipe *pipe);
  129. static void mdp4_dsi_video_wait4dmap(int cndx);
  130. static void mdp4_dsi_video_wait4ov(int cndx);
  131. int mdp4_dsi_video_pipe_commit(int cndx, int wait)
  132. {
  133. int i, undx;
  134. int mixer = 0;
  135. struct vsycn_ctrl *vctrl;
  136. struct vsync_update *vp;
  137. struct mdp4_overlay_pipe *pipe;
  138. struct mdp4_overlay_pipe *real_pipe;
  139. unsigned long flags;
  140. int cnt = 0;
  141. vctrl = &vsync_ctrl_db[cndx];
  142. mutex_lock(&vctrl->update_lock);
  143. undx = vctrl->update_ndx;
  144. vp = &vctrl->vlist[undx];
  145. pipe = vctrl->base_pipe;
  146. mixer = pipe->mixer_num;
  147. mdp_update_pm(vctrl->mfd, vctrl->vsync_time);
  148. if (vp->update_cnt == 0) {
  149. mutex_unlock(&vctrl->update_lock);
  150. return cnt;
  151. }
  152. vctrl->update_ndx++;
  153. vctrl->update_ndx &= 0x01;
  154. vp->update_cnt = 0; /* reset */
  155. if (vctrl->blt_free) {
  156. vctrl->blt_free--;
  157. if (vctrl->blt_free == 0)
  158. mdp4_free_writeback_buf(vctrl->mfd, mixer);
  159. }
  160. mutex_unlock(&vctrl->update_lock);
  161. /* free previous committed iommu back to pool */
  162. mdp4_overlay_iommu_unmap_freelist(mixer);
  163. spin_lock_irqsave(&vctrl->spin_lock, flags);
  164. if (vctrl->ov_koff != vctrl->ov_done) {
  165. spin_unlock_irqrestore(&vctrl->spin_lock, flags);
  166. pr_err("%s: Error, frame dropped %d %d\n", __func__,
  167. vctrl->ov_koff, vctrl->ov_done);
  168. return 0;
  169. }
  170. spin_unlock_irqrestore(&vctrl->spin_lock, flags);
  171. pipe = vp->plist;
  172. for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
  173. if (pipe->pipe_used) {
  174. cnt++;
  175. real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
  176. if (real_pipe && real_pipe->pipe_used) {
  177. /* pipe not unset */
  178. mdp4_overlay_vsync_commit(pipe);
  179. }
  180. /* free previous iommu to freelist
  181. * which will be freed at next
  182. * pipe_commit
  183. */
  184. mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
  185. pipe->pipe_used = 0; /* clear */
  186. }
  187. }
  188. mdp4_mixer_stage_commit(mixer);
  189. /* start timing generator & mmu if they are not started yet */
  190. mdp4_overlay_dsi_video_start();
  191. pipe = vctrl->base_pipe;
  192. spin_lock_irqsave(&vctrl->spin_lock, flags);
  193. if (pipe->ov_blt_addr) {
  194. mdp4_dsi_video_blt_ov_update(pipe);
  195. pipe->ov_cnt++;
  196. INIT_COMPLETION(vctrl->ov_comp);
  197. vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
  198. mb();
  199. vctrl->ov_koff++;
  200. /* kickoff overlay engine */
  201. mdp4_stat.kickoff_ov0++;
  202. outpdw(MDP_BASE + 0x0004, 0);
  203. } else {
  204. /* schedule second phase update at dmap */
  205. INIT_COMPLETION(vctrl->dmap_comp);
  206. vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
  207. }
  208. spin_unlock_irqrestore(&vctrl->spin_lock, flags);
  209. mdp4_stat.overlay_commit[pipe->mixer_num]++;
  210. if (wait) {
  211. if (pipe->ov_blt_addr)
  212. mdp4_dsi_video_wait4ov(cndx);
  213. else
  214. mdp4_dsi_video_wait4dmap(cndx);
  215. }
  216. return cnt;
  217. }
  218. void mdp4_dsi_video_vsync_ctrl(struct fb_info *info, int enable)
  219. {
  220. struct vsycn_ctrl *vctrl;
  221. int cndx = 0;
  222. vctrl = &vsync_ctrl_db[cndx];
  223. if (vctrl->vsync_irq_enabled == enable)
  224. return;
  225. pr_debug("%s: vsync enable=%d\n", __func__, enable);
  226. vctrl->vsync_irq_enabled = enable;
  227. if (enable)
  228. vsync_irq_enable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
  229. else
  230. vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
  231. if (vctrl->vsync_irq_enabled && atomic_read(&vctrl->suspend) == 0)
  232. atomic_set(&vctrl->vsync_resume, 1);
  233. }
  234. void mdp4_dsi_video_wait4vsync(int cndx, long long *vtime)
  235. {
  236. struct vsycn_ctrl *vctrl;
  237. struct mdp4_overlay_pipe *pipe;
  238. unsigned long flags;
  239. if (cndx >= MAX_CONTROLLER) {
  240. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  241. return;
  242. }
  243. vctrl = &vsync_ctrl_db[cndx];
  244. pipe = vctrl->base_pipe;
  245. if (atomic_read(&vctrl->suspend) > 0) {
  246. *vtime = -1;
  247. return;
  248. }
  249. /* start timing generator & mmu if they are not started yet */
  250. mdp4_overlay_dsi_video_start();
  251. spin_lock_irqsave(&vctrl->spin_lock, flags);
  252. if (vctrl->wait_vsync_cnt == 0)
  253. INIT_COMPLETION(vctrl->vsync_comp);
  254. vctrl->wait_vsync_cnt++;
  255. spin_unlock_irqrestore(&vctrl->spin_lock, flags);
  256. wait_for_completion(&vctrl->vsync_comp);
  257. mdp4_stat.wait4vsync0++;
  258. *vtime = ktime_to_ns(vctrl->vsync_time);
  259. }
  260. static void mdp4_dsi_video_wait4dmap(int cndx)
  261. {
  262. struct vsycn_ctrl *vctrl;
  263. if (cndx >= MAX_CONTROLLER) {
  264. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  265. return;
  266. }
  267. vctrl = &vsync_ctrl_db[cndx];
  268. if (atomic_read(&vctrl->suspend) > 0)
  269. return;
  270. wait_for_completion(&vctrl->dmap_comp);
  271. }
  272. static void mdp4_dsi_video_wait4dmap_done(int cndx)
  273. {
  274. unsigned long flags;
  275. struct vsycn_ctrl *vctrl;
  276. if (cndx >= MAX_CONTROLLER) {
  277. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  278. return;
  279. }
  280. vctrl = &vsync_ctrl_db[cndx];
  281. spin_lock_irqsave(&vctrl->spin_lock, flags);
  282. INIT_COMPLETION(vctrl->dmap_comp);
  283. vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
  284. spin_unlock_irqrestore(&vctrl->spin_lock, flags);
  285. mdp4_dsi_video_wait4dmap(cndx);
  286. }
  287. static void mdp4_dsi_video_wait4ov(int cndx)
  288. {
  289. struct vsycn_ctrl *vctrl;
  290. if (cndx >= MAX_CONTROLLER) {
  291. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  292. return;
  293. }
  294. vctrl = &vsync_ctrl_db[cndx];
  295. if (atomic_read(&vctrl->suspend) > 0)
  296. return;
  297. wait_for_completion(&vctrl->ov_comp);
  298. }
  299. ssize_t mdp4_dsi_video_show_event(struct device *dev,
  300. struct device_attribute *attr, char *buf)
  301. {
  302. int cndx;
  303. struct vsycn_ctrl *vctrl;
  304. ssize_t ret = 0;
  305. unsigned long flags;
  306. u64 vsync_tick;
  307. cndx = 0;
  308. vctrl = &vsync_ctrl_db[0];
  309. if (atomic_read(&vctrl->suspend) > 0 ||
  310. atomic_read(&vctrl->vsync_resume) == 0)
  311. return 0;
  312. spin_lock_irqsave(&vctrl->spin_lock, flags);
  313. if (vctrl->wait_vsync_cnt == 0)
  314. INIT_COMPLETION(vctrl->vsync_comp);
  315. vctrl->wait_vsync_cnt++;
  316. spin_unlock_irqrestore(&vctrl->spin_lock, flags);
  317. ret = wait_for_completion_interruptible_timeout(&vctrl->vsync_comp,
  318. msecs_to_jiffies(VSYNC_PERIOD * 4));
  319. if (ret <= 0) {
  320. vctrl->wait_vsync_cnt = 0;
  321. vsync_tick = ktime_to_ns(ktime_get());
  322. ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
  323. buf[strlen(buf) + 1] = '\0';
  324. return ret;
  325. }
  326. spin_lock_irqsave(&vctrl->spin_lock, flags);
  327. vsync_tick = ktime_to_ns(vctrl->vsync_time);
  328. spin_unlock_irqrestore(&vctrl->spin_lock, flags);
  329. ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
  330. buf[strlen(buf) + 1] = '\0';
  331. return ret;
  332. }
  333. void mdp4_dsi_vsync_init(int cndx)
  334. {
  335. struct vsycn_ctrl *vctrl;
  336. if (cndx >= MAX_CONTROLLER) {
  337. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  338. return;
  339. }
  340. pr_debug("%s: ndx=%d\n", __func__, cndx);
  341. vctrl = &vsync_ctrl_db[cndx];
  342. if (vctrl->inited)
  343. return;
  344. vctrl->inited = 1;
  345. vctrl->update_ndx = 0;
  346. mutex_init(&vctrl->update_lock);
  347. init_completion(&vctrl->vsync_comp);
  348. init_completion(&vctrl->dmap_comp);
  349. init_completion(&vctrl->ov_comp);
  350. atomic_set(&vctrl->suspend, 1);
  351. atomic_set(&vctrl->vsync_resume, 1);
  352. spin_lock_init(&vctrl->spin_lock);
  353. }
  354. void mdp4_dsi_video_base_swap(int cndx, struct mdp4_overlay_pipe *pipe)
  355. {
  356. struct vsycn_ctrl *vctrl;
  357. if (cndx >= MAX_CONTROLLER) {
  358. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  359. return;
  360. }
  361. vctrl = &vsync_ctrl_db[cndx];
  362. vctrl->base_pipe = pipe;
  363. }
  364. int mdp4_dsi_video_on(struct platform_device *pdev)
  365. {
  366. int dsi_width;
  367. int dsi_height;
  368. int dsi_bpp;
  369. int dsi_border_clr;
  370. int dsi_underflow_clr;
  371. int dsi_hsync_skew;
  372. int hsync_period;
  373. int hsync_ctrl;
  374. int vsync_period;
  375. int display_hctl;
  376. int display_v_start;
  377. int display_v_end;
  378. int active_hctl;
  379. int active_h_start;
  380. int active_h_end;
  381. int active_v_start;
  382. int active_v_end;
  383. int ctrl_polarity;
  384. int h_back_porch;
  385. int h_front_porch;
  386. int v_back_porch;
  387. int v_front_porch;
  388. int hsync_pulse_width;
  389. int vsync_pulse_width;
  390. int hsync_polarity;
  391. int vsync_polarity;
  392. int data_en_polarity;
  393. int hsync_start_x;
  394. int hsync_end_x;
  395. uint8 *buf;
  396. unsigned int buf_offset;
  397. int bpp, ptype;
  398. struct fb_info *fbi;
  399. struct fb_var_screeninfo *var;
  400. struct msm_fb_data_type *mfd;
  401. struct mdp4_overlay_pipe *pipe;
  402. int ret = 0;
  403. int cndx = 0;
  404. struct vsycn_ctrl *vctrl;
  405. struct msm_panel_info *pinfo;
  406. vctrl = &vsync_ctrl_db[cndx];
  407. mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
  408. if (!mfd)
  409. return -ENODEV;
  410. if (mfd->key != MFD_KEY)
  411. return -EINVAL;
  412. vctrl->mfd = mfd;
  413. vctrl->dev = mfd->fbi->dev;
  414. pinfo = &mfd->panel_info;
  415. vctrl->blt_ctrl = pinfo->lcd.blt_ctrl;
  416. vctrl->blt_mode = pinfo->lcd.blt_mode;
  417. /* mdp clock on */
  418. mdp_clk_ctrl(1);
  419. fbi = mfd->fbi;
  420. var = &fbi->var;
  421. bpp = fbi->var.bits_per_pixel / 8;
  422. buf = (uint8 *) fbi->fix.smem_start;
  423. buf_offset = calc_fb_offset(mfd, fbi, bpp);
  424. if (vctrl->base_pipe == NULL) {
  425. ptype = mdp4_overlay_format2type(mfd->fb_imgType);
  426. if (ptype < 0)
  427. printk(KERN_INFO "%s: format2type failed\n", __func__);
  428. pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0);
  429. if (pipe == NULL) {
  430. printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
  431. return -EBUSY;
  432. }
  433. pipe->pipe_used++;
  434. pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
  435. pipe->mixer_num = MDP4_MIXER0;
  436. pipe->src_format = mfd->fb_imgType;
  437. mdp4_overlay_panel_mode(pipe->mixer_num, MDP4_PANEL_DSI_VIDEO);
  438. ret = mdp4_overlay_format2pipe(pipe);
  439. if (ret < 0)
  440. printk(KERN_INFO "%s: format2type failed\n", __func__);
  441. pipe->ov_blt_addr = 0;
  442. pipe->dma_blt_addr = 0;
  443. vctrl->base_pipe = pipe; /* keep it */
  444. mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
  445. } else {
  446. pipe = vctrl->base_pipe;
  447. }
  448. if (!(mfd->cont_splash_done)) {
  449. mfd->cont_splash_done = 1;
  450. mdp4_dsi_video_wait4dmap_done(0);
  451. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
  452. dsi_video_enabled = 0;
  453. mipi_dsi_controller_cfg(0);
  454. /* Clks are enabled in probe.
  455. Disabling clocks now */
  456. mdp_clk_ctrl(0);
  457. }
  458. pipe->src_height = fbi->var.yres;
  459. pipe->src_width = fbi->var.xres;
  460. pipe->src_h = fbi->var.yres;
  461. pipe->src_w = fbi->var.xres;
  462. pipe->src_y = 0;
  463. pipe->src_x = 0;
  464. pipe->dst_h = fbi->var.yres;
  465. pipe->dst_w = fbi->var.xres;
  466. pipe->srcp0_ystride = fbi->fix.line_length;
  467. pipe->bpp = bpp;
  468. if (mfd->display_iova)
  469. pipe->srcp0_addr = mfd->display_iova + buf_offset;
  470. else
  471. pipe->srcp0_addr = (uint32)(buf + buf_offset);
  472. pipe->dst_h = fbi->var.yres;
  473. pipe->dst_w = fbi->var.xres;
  474. mdp4_overlay_mdp_pipe_req(pipe, mfd);
  475. mdp4_calc_blt_mdp_bw(mfd, pipe);
  476. atomic_set(&vctrl->suspend, 0);
  477. mdp4_overlay_dmap_xy(pipe); /* dma_p */
  478. mdp4_overlay_dmap_cfg(mfd, 1);
  479. mdp4_overlay_rgb_setup(pipe);
  480. mdp4_overlayproc_cfg(pipe);
  481. mdp4_overlay_reg_flush(pipe, 1);
  482. mdp4_mixer_stage_up(pipe, 0);
  483. mdp4_mixer_stage_commit(pipe->mixer_num);
  484. /*
  485. * DSI timing setting
  486. */
  487. h_back_porch = var->left_margin;
  488. h_front_porch = var->right_margin;
  489. v_back_porch = var->upper_margin;
  490. v_front_porch = var->lower_margin;
  491. hsync_pulse_width = var->hsync_len;
  492. vsync_pulse_width = var->vsync_len;
  493. dsi_border_clr = mfd->panel_info.lcdc.border_clr;
  494. dsi_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
  495. dsi_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
  496. dsi_width = mfd->panel_info.xres +
  497. mfd->panel_info.lcdc.xres_pad;
  498. dsi_height = mfd->panel_info.yres +
  499. mfd->panel_info.lcdc.yres_pad;
  500. dsi_bpp = mfd->panel_info.bpp;
  501. hsync_period = hsync_pulse_width + h_back_porch + dsi_width
  502. + h_front_porch;
  503. hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
  504. hsync_start_x = h_back_porch + hsync_pulse_width;
  505. hsync_end_x = hsync_period - h_front_porch - 1;
  506. display_hctl = (hsync_end_x << 16) | hsync_start_x;
  507. vsync_period =
  508. (vsync_pulse_width + v_back_porch + dsi_height + v_front_porch);
  509. display_v_start = ((vsync_pulse_width + v_back_porch) * hsync_period)
  510. + dsi_hsync_skew;
  511. display_v_end =
  512. ((vsync_period - v_front_porch) * hsync_period) + dsi_hsync_skew - 1;
  513. if (dsi_width != var->xres) {
  514. active_h_start = hsync_start_x + first_pixel_start_x;
  515. active_h_end = active_h_start + var->xres - 1;
  516. active_hctl =
  517. ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
  518. } else {
  519. active_hctl = 0;
  520. }
  521. if (dsi_height != var->yres) {
  522. active_v_start =
  523. display_v_start + first_pixel_start_y * hsync_period;
  524. active_v_end = active_v_start + (var->yres) * hsync_period - 1;
  525. active_v_start |= ACTIVE_START_Y_EN;
  526. } else {
  527. active_v_start = 0;
  528. active_v_end = 0;
  529. }
  530. dsi_underflow_clr |= 0x80000000; /* enable recovery */
  531. hsync_polarity = 0;
  532. vsync_polarity = 0;
  533. data_en_polarity = 0;
  534. ctrl_polarity =
  535. (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
  536. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
  537. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x4, hsync_ctrl);
  538. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x8, vsync_period * hsync_period);
  539. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0xc,
  540. vsync_pulse_width * hsync_period);
  541. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x10, display_hctl);
  542. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x14, display_v_start);
  543. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x18, display_v_end);
  544. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x1c, active_hctl);
  545. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x20, active_v_start);
  546. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x24, active_v_end);
  547. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x28, dsi_border_clr);
  548. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x2c, dsi_underflow_clr);
  549. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x30, dsi_hsync_skew);
  550. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x38, ctrl_polarity);
  551. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
  552. mdp_histogram_ctrl_all(TRUE);
  553. return ret;
  554. }
  555. int mdp4_dsi_video_off(struct platform_device *pdev)
  556. {
  557. int ret = 0;
  558. int cndx = 0;
  559. struct msm_fb_data_type *mfd;
  560. struct vsycn_ctrl *vctrl;
  561. struct mdp4_overlay_pipe *pipe;
  562. struct vsync_update *vp;
  563. unsigned long flags;
  564. int undx, need_wait = 0;
  565. mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
  566. vctrl = &vsync_ctrl_db[cndx];
  567. pipe = vctrl->base_pipe;
  568. atomic_set(&vctrl->suspend, 1);
  569. atomic_set(&vctrl->vsync_resume, 0);
  570. msleep(20); /* >= 17 ms */
  571. complete_all(&vctrl->vsync_comp);
  572. if (pipe->ov_blt_addr) {
  573. spin_lock_irqsave(&vctrl->spin_lock, flags);
  574. if (vctrl->ov_koff != vctrl->ov_done)
  575. need_wait = 1;
  576. spin_unlock_irqrestore(&vctrl->spin_lock, flags);
  577. if (need_wait)
  578. mdp4_dsi_video_wait4ov(0);
  579. }
  580. mdp_histogram_ctrl_all(FALSE);
  581. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
  582. dsi_video_enabled = 0;
  583. if (vctrl->vsync_irq_enabled) {
  584. vctrl->vsync_irq_enabled = 0;
  585. vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
  586. }
  587. undx = vctrl->update_ndx;
  588. vp = &vctrl->vlist[undx];
  589. if (vp->update_cnt) {
  590. /*
  591. * pipe's iommu will be freed at next overlay play
  592. * and iommu_drop statistic will be increased by one
  593. */
  594. vp->update_cnt = 0; /* empty queue */
  595. }
  596. if (pipe) {
  597. /* sanity check, free pipes besides base layer */
  598. mdp4_overlay_unset_mixer(pipe->mixer_num);
  599. if (mfd->ref_cnt == 0) {
  600. /* adb stop */
  601. if (pipe->pipe_type == OVERLAY_TYPE_BF)
  602. mdp4_overlay_borderfill_stage_down(pipe);
  603. /* base pipe may change after borderfill_stage_down */
  604. pipe = vctrl->base_pipe;
  605. mdp4_mixer_stage_down(pipe, 1);
  606. mdp4_overlay_pipe_free(pipe);
  607. vctrl->base_pipe = NULL;
  608. } else {
  609. /* system suspending */
  610. mdp4_mixer_stage_down(vctrl->base_pipe, 1);
  611. mdp4_overlay_iommu_pipe_free(
  612. vctrl->base_pipe->pipe_ndx, 1);
  613. }
  614. }
  615. /* mdp clock off */
  616. mdp_clk_ctrl(0);
  617. mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
  618. return ret;
  619. }
  620. static __u32 msm_fb_line_length(__u32 fb_index, __u32 xres, int bpp)
  621. {
  622. /*
  623. * The adreno GPU hardware requires that the pitch be aligned to
  624. * 32 pixels for color buffers, so for the cases where the GPU
  625. * is writing directly to fb0, the framebuffer pitch
  626. * also needs to be 32 pixel aligned
  627. */
  628. if (fb_index == 0)
  629. return ALIGN(xres, 32) * bpp;
  630. else
  631. return xres * bpp;
  632. }
  633. /* 3D side by side */
  634. void mdp4_dsi_video_3d_sbys(struct msm_fb_data_type *mfd,
  635. struct msmfb_overlay_3d *r3d)
  636. {
  637. struct fb_info *fbi;
  638. unsigned int buf_offset;
  639. int bpp;
  640. uint8 *buf = NULL;
  641. int cndx = 0;
  642. struct vsycn_ctrl *vctrl;
  643. struct mdp4_overlay_pipe *pipe;
  644. vctrl = &vsync_ctrl_db[cndx];
  645. pipe = vctrl->base_pipe;
  646. if (vctrl->base_pipe == NULL)
  647. return;
  648. pipe = vctrl->base_pipe;
  649. pipe->is_3d = r3d->is_3d;
  650. pipe->src_height_3d = r3d->height;
  651. pipe->src_width_3d = r3d->width;
  652. if (pipe->is_3d)
  653. mdp4_overlay_panel_3d(pipe->mixer_num, MDP4_3D_SIDE_BY_SIDE);
  654. else
  655. mdp4_overlay_panel_3d(pipe->mixer_num, MDP4_3D_NONE);
  656. fbi = mfd->fbi;
  657. bpp = fbi->var.bits_per_pixel / 8;
  658. buf = (uint8 *) fbi->fix.smem_start;
  659. buf_offset = calc_fb_offset(mfd, fbi, bpp);
  660. if (pipe->is_3d) {
  661. pipe->src_height = pipe->src_height_3d;
  662. pipe->src_width = pipe->src_width_3d;
  663. pipe->src_h = pipe->src_height_3d;
  664. pipe->src_w = pipe->src_width_3d;
  665. pipe->dst_h = pipe->src_height_3d;
  666. pipe->dst_w = pipe->src_width_3d;
  667. pipe->srcp0_ystride = msm_fb_line_length(0,
  668. pipe->src_width, bpp);
  669. } else {
  670. /* 2D */
  671. pipe->src_height = fbi->var.yres;
  672. pipe->src_width = fbi->var.xres;
  673. pipe->src_h = fbi->var.yres;
  674. pipe->src_w = fbi->var.xres;
  675. pipe->dst_h = fbi->var.yres;
  676. pipe->dst_w = fbi->var.xres;
  677. pipe->srcp0_ystride = fbi->fix.line_length;
  678. }
  679. pipe->src_y = 0;
  680. pipe->src_x = 0;
  681. pipe->dst_y = 0;
  682. pipe->dst_x = 0;
  683. if (mfd->display_iova)
  684. pipe->srcp0_addr = mfd->display_iova + buf_offset;
  685. else
  686. pipe->srcp0_addr = (uint32)(buf + buf_offset);
  687. mdp4_overlay_rgb_setup(pipe);
  688. mdp4_overlayproc_cfg(pipe);
  689. mdp4_overlay_dmap_xy(pipe);
  690. mdp4_overlay_dmap_cfg(mfd, 1);
  691. mdp4_overlay_reg_flush(pipe, 1);
  692. mdp4_mixer_stage_up(pipe, 0);
  693. mdp4_mixer_stage_commit(pipe->mixer_num);
  694. mb();
  695. }
  696. static void mdp4_dsi_video_blt_ov_update(struct mdp4_overlay_pipe *pipe)
  697. {
  698. uint32 off, addr;
  699. int bpp;
  700. char *overlay_base;
  701. if (pipe->ov_blt_addr == 0)
  702. return;
  703. #ifdef BLT_RGB565
  704. bpp = 2; /* overlay ouput is RGB565 */
  705. #else
  706. bpp = 3; /* overlay ouput is RGB888 */
  707. #endif
  708. off = 0;
  709. if (pipe->ov_cnt & 0x01)
  710. off = pipe->src_height * pipe->src_width * bpp;
  711. addr = pipe->ov_blt_addr + off;
  712. /* overlay 0 */
  713. overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
  714. outpdw(overlay_base + 0x000c, addr);
  715. outpdw(overlay_base + 0x001c, addr);
  716. }
  717. static void mdp4_dsi_video_blt_dmap_update(struct mdp4_overlay_pipe *pipe)
  718. {
  719. uint32 off, addr;
  720. int bpp;
  721. if (pipe->ov_blt_addr == 0)
  722. return;
  723. #ifdef BLT_RGB565
  724. bpp = 2; /* overlay ouput is RGB565 */
  725. #else
  726. bpp = 3; /* overlay ouput is RGB888 */
  727. #endif
  728. off = 0;
  729. if (pipe->dmap_cnt & 0x01)
  730. off = pipe->src_height * pipe->src_width * bpp;
  731. addr = pipe->dma_blt_addr + off;
  732. /* dmap */
  733. MDP_OUTP(MDP_BASE + 0x90008, addr);
  734. }
  735. /*
  736. * mdp4_primary_vsync_dsi_video: called from isr
  737. */
  738. void mdp4_primary_vsync_dsi_video(void)
  739. {
  740. int cndx;
  741. struct vsycn_ctrl *vctrl;
  742. cndx = 0;
  743. vctrl = &vsync_ctrl_db[cndx];
  744. pr_debug("%s: cpu=%d\n", __func__, smp_processor_id());
  745. spin_lock(&vctrl->spin_lock);
  746. vctrl->vsync_time = ktime_get();
  747. if (vctrl->wait_vsync_cnt) {
  748. complete_all(&vctrl->vsync_comp);
  749. vctrl->wait_vsync_cnt = 0;
  750. }
  751. spin_unlock(&vctrl->spin_lock);
  752. }
  753. /*
  754. * mdp4_dmap_done_dsi_video: called from isr
  755. */
  756. void mdp4_dmap_done_dsi_video(int cndx)
  757. {
  758. struct vsycn_ctrl *vctrl;
  759. struct mdp4_overlay_pipe *pipe;
  760. if (cndx >= MAX_CONTROLLER) {
  761. pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
  762. return;
  763. }
  764. vctrl = &vsync_ctrl_db[cndx];
  765. pipe = vctrl->base_pipe;
  766. if (pipe == NULL)
  767. return;
  768. spin_lock(&vctrl->spin_lock);
  769. vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
  770. if (vctrl->blt_change) {
  771. mdp4_overlayproc_cfg(pipe);
  772. mdp4_overlay_dmap_xy(pipe);
  773. vctrl->blt_change = 0;
  774. }
  775. complete_all(&vctrl->dmap_comp);
  776. mdp4_overlay_dma_commit(cndx);
  777. spin_unlock(&vctrl->spin_lock);
  778. }
  779. /*
  780. * mdp4_overlay0_done_dsi: called from isr
  781. */
  782. void mdp4_overlay0_done_dsi_video(int cndx)
  783. {
  784. struct vsycn_ctrl *vctrl;
  785. struct mdp4_overlay_pipe *pipe;
  786. vctrl = &vsync_ctrl_db[cndx];
  787. pipe = vctrl->base_pipe;
  788. if (pipe == NULL)
  789. return;
  790. spin_lock(&vctrl->spin_lock);
  791. vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
  792. vctrl->ov_done++;
  793. complete_all(&vctrl->ov_comp);
  794. if (pipe->ov_blt_addr == 0) {
  795. spin_unlock(&vctrl->spin_lock);
  796. return;
  797. }
  798. mdp4_dsi_video_blt_dmap_update(pipe);
  799. pipe->dmap_cnt++;
  800. spin_unlock(&vctrl->spin_lock);
  801. }
  802. /*
  803. * make sure the MIPI_DSI_WRITEBACK_SIZE defined at boardfile
  804. * has enough space h * w * 3 * 2
  805. */
  806. static void mdp4_dsi_video_do_blt(struct msm_fb_data_type *mfd, int enable)
  807. {
  808. unsigned long flag;
  809. int cndx = 0;
  810. struct vsycn_ctrl *vctrl;
  811. struct mdp4_overlay_pipe *pipe;
  812. long long vtime;
  813. u32 mode, ctrl;
  814. vctrl = &vsync_ctrl_db[cndx];
  815. pipe = vctrl->base_pipe;
  816. mode = (dbg_force_ov0_blt & 0x0f) ?
  817. (dbg_force_ov0_blt & 0x0f) : vctrl->blt_mode;
  818. ctrl = (dbg_force_ov0_blt >> 4) ?
  819. (dbg_force_ov0_blt >> 4) : vctrl->blt_ctrl;
  820. pr_debug("%s: mode=%d, enable=%d ov_blt_addr=%x\n",
  821. __func__, mode, enable, (int)pipe->ov_blt_addr);
  822. if ((mode == MDP4_OVERLAY_MODE_BLT_ALWAYS_OFF) &&
  823. !pipe->ov_blt_addr)
  824. return;
  825. else if ((mode == MDP4_OVERLAY_MODE_BLT_ALWAYS_ON) &&
  826. pipe->ov_blt_addr)
  827. return;
  828. else if (enable && pipe->ov_blt_addr)
  829. return;
  830. else if (!enable && !pipe->ov_blt_addr)
  831. return;
  832. if (pipe->ov_blt_addr == 0) {
  833. mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
  834. if (mfd->ov0_wb_buf->write_addr == 0) {
  835. pr_warning("%s: no blt_base assigned\n", __func__);
  836. return;
  837. }
  838. }
  839. pr_debug("%s: mode=%d, enable=%d ov_blt_addr=%x\n",
  840. __func__, mode, enable, (int)pipe->ov_blt_addr);
  841. spin_lock_irqsave(&vctrl->spin_lock, flag);
  842. if (pipe->ov_blt_addr == 0) {
  843. pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
  844. pipe->dma_blt_addr = mfd->ov0_wb_buf->read_addr;
  845. pipe->ov_cnt = 0;
  846. pipe->dmap_cnt = 0;
  847. vctrl->ov_koff = 0;
  848. vctrl->ov_done = 0;
  849. vctrl->blt_free = 0;
  850. mdp4_stat.blt_dsi_video++;
  851. } else {
  852. pipe->ov_blt_addr = 0;
  853. pipe->dma_blt_addr = 0;
  854. vctrl->blt_free = 4; /* 4 commits to free wb buf */
  855. }
  856. spin_unlock_irqrestore(&vctrl->spin_lock, flag);
  857. if (ctrl == MDP4_OVERLAY_BLT_SWITCH_TG_ON) {
  858. spin_lock_irqsave(&vctrl->spin_lock, flag);
  859. if (!dsi_video_enabled) {
  860. pr_debug("%s: blt switched not in ISR dsi_video_enabled=%d\n",
  861. __func__, dsi_video_enabled);
  862. mdp4_overlayproc_cfg(pipe);
  863. mdp4_overlay_dmap_xy(pipe);
  864. } else {
  865. pr_debug("%s: blt switched in ISR dsi_video_enabled=%d\n",
  866. __func__, dsi_video_enabled);
  867. vctrl->blt_change++;
  868. }
  869. spin_unlock_irqrestore(&vctrl->spin_lock, flag);
  870. if (dsi_video_enabled)
  871. mdp4_dsi_video_wait4dmap_done(0);
  872. } else if (ctrl == MDP4_OVERLAY_BLT_SWITCH_TG_OFF) {
  873. pr_debug("%s: blt switched by turning TG off\n", __func__);
  874. if (dsi_video_enabled) {
  875. mdp4_dsi_video_wait4vsync(0, &vtime);
  876. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
  877. mdp4_dsi_video_wait4dmap_done(0);
  878. }
  879. mdp4_overlayproc_cfg(pipe);
  880. mdp4_overlay_dmap_xy(pipe);
  881. if (dsi_video_enabled) {
  882. /*
  883. * need wait for more than 1 ms to
  884. * make sure dsi lanes' fifo is empty and
  885. * lanes in stop state befroe reset
  886. * controller
  887. */
  888. usleep(2000);
  889. mipi_dsi_sw_reset();
  890. MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1);
  891. }
  892. } else if (ctrl == MDP4_OVERLAY_BLT_SWITCH_POLL) {
  893. pr_debug("%s: blt switched by polling mdp status\n", __func__);
  894. if (dsi_video_enabled)
  895. while (inpdw(MDP_BASE + 0x0018) & 0x05)
  896. cpu_relax();
  897. mdp4_overlayproc_cfg(pipe);
  898. mdp4_overlay_dmap_xy(pipe);
  899. } else
  900. pr_err("%s: ctrl=%d is not supported\n", __func__, ctrl);
  901. }
  902. void mdp4_dsi_video_overlay_blt(struct msm_fb_data_type *mfd,
  903. struct msmfb_overlay_blt *req)
  904. {
  905. mdp4_dsi_video_do_blt(mfd, req->enable);
  906. }
  907. void mdp4_dsi_video_blt_start(struct msm_fb_data_type *mfd)
  908. {
  909. mdp4_dsi_video_do_blt(mfd, 1);
  910. }
  911. void mdp4_dsi_video_blt_stop(struct msm_fb_data_type *mfd)
  912. {
  913. mdp4_dsi_video_do_blt(mfd, 0);
  914. }
  915. void mdp4_dsi_video_overlay(struct msm_fb_data_type *mfd)
  916. {
  917. struct fb_info *fbi = mfd->fbi;
  918. uint8 *buf;
  919. unsigned int buf_offset;
  920. int bpp;
  921. int cnt, cndx = 0;
  922. struct vsycn_ctrl *vctrl;
  923. struct mdp4_overlay_pipe *pipe;
  924. mutex_lock(&mfd->dma->ov_mutex);
  925. vctrl = &vsync_ctrl_db[cndx];
  926. pipe = vctrl->base_pipe;
  927. if (!pipe || !mfd->panel_power_on) {
  928. mutex_unlock(&mfd->dma->ov_mutex);
  929. return;
  930. }
  931. pr_debug("%s: cpu=%d pid=%d\n", __func__,
  932. smp_processor_id(), current->pid);
  933. if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
  934. bpp = fbi->var.bits_per_pixel / 8;
  935. buf = (uint8 *) fbi->fix.smem_start;
  936. buf_offset = calc_fb_offset(mfd, fbi, bpp);
  937. if (mfd->display_iova)
  938. pipe->srcp0_addr = mfd->display_iova + buf_offset;
  939. else
  940. pipe->srcp0_addr = (uint32)(buf + buf_offset);
  941. mdp4_dsi_video_pipe_queue(0, pipe);
  942. }
  943. mdp4_overlay_mdp_perf_upd(mfd, 1);
  944. cnt = mdp4_dsi_video_pipe_commit(cndx, 0);
  945. if (cnt) {
  946. if (pipe->ov_blt_addr)
  947. mdp4_dsi_video_wait4ov(cndx);
  948. else
  949. mdp4_dsi_video_wait4dmap(cndx);
  950. }
  951. mdp4_overlay_mdp_perf_upd(mfd, 0);
  952. mutex_unlock(&mfd->dma->ov_mutex);
  953. }