mdp3_dma.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169
  1. /* Copyright (c) 2013-2014, 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/bitops.h>
  14. #include <linux/iopoll.h>
  15. #include "mdp3.h"
  16. #include "mdp3_dma.h"
  17. #include "mdp3_hwio.h"
  18. #include "mdss_debug.h"
  19. #define DMA_STOP_POLL_SLEEP_US 1000
  20. #define DMA_STOP_POLL_TIMEOUT_US 200000
  21. #define DMA_HISTO_RESET_TIMEOUT_MS 40
  22. #define DMA_LUT_CONFIG_MASK 0xfffffbe8
  23. #define DMA_CCS_CONFIG_MASK 0xfffffc17
  24. #define HIST_WAIT_TIMEOUT(frame) ((75 * HZ * (frame)) / 1000)
  25. #define VSYNC_SELECT 0x024
  26. #define VSYNC_TOTAL_LINES_SHIFT 21
  27. #define VSYNC_COUNT_MASK 0x7ffff
  28. #define VSYNC_THRESH_CONT_SHIFT 16
  29. static void mdp3_vsync_intr_handler(int type, void *arg)
  30. {
  31. struct mdp3_dma *dma = (struct mdp3_dma *)arg;
  32. struct mdp3_notification vsync_client;
  33. unsigned int wait_for_next_vs;
  34. pr_debug("mdp3_vsync_intr_handler\n");
  35. spin_lock(&dma->dma_lock);
  36. vsync_client = dma->vsync_client;
  37. wait_for_next_vs = !dma->vsync_status;
  38. dma->vsync_status = 0;
  39. if (wait_for_next_vs)
  40. complete(&dma->vsync_comp);
  41. spin_unlock(&dma->dma_lock);
  42. if (vsync_client.handler) {
  43. vsync_client.handler(vsync_client.arg);
  44. } else {
  45. if (wait_for_next_vs)
  46. mdp3_irq_disable_nosync(type);
  47. }
  48. }
  49. static void mdp3_dma_done_intr_handler(int type, void *arg)
  50. {
  51. struct mdp3_dma *dma = (struct mdp3_dma *)arg;
  52. struct mdp3_notification dma_client;
  53. pr_debug("mdp3_dma_done_intr_handler\n");
  54. spin_lock(&dma->dma_lock);
  55. dma_client = dma->dma_notifier_client;
  56. complete(&dma->dma_comp);
  57. spin_unlock(&dma->dma_lock);
  58. mdp3_irq_disable_nosync(type);
  59. if (dma_client.handler)
  60. dma_client.handler(dma_client.arg);
  61. }
  62. static void mdp3_hist_done_intr_handler(int type, void *arg)
  63. {
  64. struct mdp3_dma *dma = (struct mdp3_dma *)arg;
  65. u32 isr, mask;
  66. isr = MDP3_REG_READ(MDP3_REG_DMA_P_HIST_INTR_STATUS);
  67. mask = MDP3_REG_READ(MDP3_REG_DMA_P_HIST_INTR_ENABLE);
  68. MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_CLEAR, isr);
  69. isr &= mask;
  70. if (isr == 0)
  71. return;
  72. if (isr & MDP3_DMA_P_HIST_INTR_HIST_DONE_BIT) {
  73. spin_lock(&dma->histo_lock);
  74. dma->histo_state = MDP3_DMA_HISTO_STATE_READY;
  75. complete(&dma->histo_comp);
  76. spin_unlock(&dma->histo_lock);
  77. }
  78. if (isr & MDP3_DMA_P_HIST_INTR_RESET_DONE_BIT) {
  79. spin_lock(&dma->histo_lock);
  80. dma->histo_state = MDP3_DMA_HISTO_STATE_IDLE;
  81. complete(&dma->histo_comp);
  82. spin_unlock(&dma->histo_lock);
  83. }
  84. }
  85. void mdp3_dma_callback_enable(struct mdp3_dma *dma, int type)
  86. {
  87. int irq_bit;
  88. pr_debug("mdp3_dma_callback_enable type=%d\n", type);
  89. if (dma->dma_sel == MDP3_DMA_P) {
  90. if (type & MDP3_DMA_CALLBACK_TYPE_HIST_RESET_DONE)
  91. mdp3_irq_enable(MDP3_INTR_DMA_P_HISTO);
  92. if (type & MDP3_DMA_CALLBACK_TYPE_HIST_DONE)
  93. mdp3_irq_enable(MDP3_INTR_DMA_P_HISTO);
  94. }
  95. if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
  96. dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC) {
  97. if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC)
  98. mdp3_irq_enable(MDP3_INTR_LCDC_START_OF_FRAME);
  99. } else if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
  100. if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC) {
  101. irq_bit = MDP3_INTR_SYNC_PRIMARY_LINE;
  102. irq_bit += dma->dma_sel;
  103. mdp3_irq_enable(irq_bit);
  104. }
  105. if (type & MDP3_DMA_CALLBACK_TYPE_DMA_DONE) {
  106. irq_bit = MDP3_INTR_DMA_P_DONE;
  107. if (dma->dma_sel == MDP3_DMA_S)
  108. irq_bit = MDP3_INTR_DMA_S_DONE;
  109. mdp3_irq_enable(irq_bit);
  110. }
  111. } else {
  112. pr_err("mdp3_dma_callback_enable not supported interface\n");
  113. }
  114. }
  115. void mdp3_dma_callback_disable(struct mdp3_dma *dma, int type)
  116. {
  117. int irq_bit;
  118. pr_debug("mdp3_dma_callback_disable type=%d\n", type);
  119. if (dma->dma_sel == MDP3_DMA_P) {
  120. if (type & MDP3_DMA_CALLBACK_TYPE_HIST_RESET_DONE)
  121. mdp3_irq_disable(MDP3_INTR_DMA_P_HISTO);
  122. if (type & MDP3_DMA_CALLBACK_TYPE_HIST_DONE)
  123. mdp3_irq_disable(MDP3_INTR_DMA_P_HISTO);
  124. }
  125. if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
  126. dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC) {
  127. if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC)
  128. mdp3_irq_disable(MDP3_INTR_LCDC_START_OF_FRAME);
  129. } else if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
  130. if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC) {
  131. irq_bit = MDP3_INTR_SYNC_PRIMARY_LINE;
  132. irq_bit += dma->dma_sel;
  133. mdp3_irq_disable(irq_bit);
  134. }
  135. if (type & MDP3_DMA_CALLBACK_TYPE_DMA_DONE) {
  136. irq_bit = MDP3_INTR_DMA_P_DONE;
  137. if (dma->dma_sel == MDP3_DMA_S)
  138. irq_bit = MDP3_INTR_DMA_S_DONE;
  139. mdp3_irq_disable(irq_bit);
  140. }
  141. }
  142. }
  143. static int mdp3_dma_callback_setup(struct mdp3_dma *dma)
  144. {
  145. int rc = 0;
  146. struct mdp3_intr_cb vsync_cb = {
  147. .cb = mdp3_vsync_intr_handler,
  148. .data = dma,
  149. };
  150. struct mdp3_intr_cb dma_cb = {
  151. .cb = mdp3_dma_done_intr_handler,
  152. .data = dma,
  153. };
  154. struct mdp3_intr_cb hist_cb = {
  155. .cb = mdp3_hist_done_intr_handler,
  156. .data = dma,
  157. };
  158. if (dma->dma_sel == MDP3_DMA_P)
  159. rc = mdp3_set_intr_callback(MDP3_INTR_DMA_P_HISTO, &hist_cb);
  160. if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
  161. dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC)
  162. rc |= mdp3_set_intr_callback(MDP3_INTR_LCDC_START_OF_FRAME,
  163. &vsync_cb);
  164. else if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
  165. int irq_bit = MDP3_INTR_SYNC_PRIMARY_LINE;
  166. irq_bit += dma->dma_sel;
  167. rc |= mdp3_set_intr_callback(irq_bit, &vsync_cb);
  168. irq_bit = MDP3_INTR_DMA_P_DONE;
  169. if (dma->dma_sel == MDP3_DMA_S)
  170. irq_bit = MDP3_INTR_DMA_S_DONE;
  171. rc |= mdp3_set_intr_callback(irq_bit, &dma_cb);
  172. } else {
  173. pr_err("mdp3_dma_callback_setup not suppported interface\n");
  174. rc = -ENODEV;
  175. }
  176. return rc;
  177. }
  178. static void mdp3_dma_vsync_enable(struct mdp3_dma *dma,
  179. struct mdp3_notification *vsync_client)
  180. {
  181. unsigned long flag;
  182. int updated = 0;
  183. int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
  184. pr_debug("mdp3_dma_vsync_enable\n");
  185. spin_lock_irqsave(&dma->dma_lock, flag);
  186. if (vsync_client) {
  187. if (dma->vsync_client.handler != vsync_client->handler) {
  188. dma->vsync_client = *vsync_client;
  189. updated = 1;
  190. }
  191. } else {
  192. if (dma->vsync_client.handler) {
  193. dma->vsync_client.handler = NULL;
  194. dma->vsync_client.arg = NULL;
  195. updated = 1;
  196. }
  197. }
  198. spin_unlock_irqrestore(&dma->dma_lock, flag);
  199. if (updated) {
  200. if (vsync_client && vsync_client->handler)
  201. mdp3_dma_callback_enable(dma, cb_type);
  202. else
  203. mdp3_dma_callback_disable(dma, cb_type);
  204. }
  205. }
  206. static void mdp3_dma_done_notifier(struct mdp3_dma *dma,
  207. struct mdp3_notification *dma_client)
  208. {
  209. unsigned long flag;
  210. spin_lock_irqsave(&dma->dma_lock, flag);
  211. if (dma_client) {
  212. dma->dma_notifier_client = *dma_client;
  213. } else {
  214. dma->dma_notifier_client.handler = NULL;
  215. dma->dma_notifier_client.arg = NULL;
  216. }
  217. spin_unlock_irqrestore(&dma->dma_lock, flag);
  218. }
  219. static void mdp3_dma_clk_auto_gating(struct mdp3_dma *dma, int enable)
  220. {
  221. u32 cgc;
  222. int clock_bit = 10;
  223. clock_bit += dma->dma_sel;
  224. if (enable) {
  225. cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
  226. cgc |= BIT(clock_bit);
  227. MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
  228. } else {
  229. cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
  230. cgc &= ~BIT(clock_bit);
  231. MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
  232. }
  233. }
  234. int mdp3_dma_sync_config(struct mdp3_dma *dma,
  235. struct mdp3_dma_source *source_config, struct mdp3_tear_check *te)
  236. {
  237. u32 vsync_clk_speed_hz, vclks_line, cfg;
  238. int porch = source_config->vporch;
  239. int height = source_config->height;
  240. int total_lines = height + porch;
  241. int dma_sel = dma->dma_sel;
  242. vsync_clk_speed_hz = MDP_VSYNC_CLK_RATE;
  243. cfg = total_lines << VSYNC_TOTAL_LINES_SHIFT;
  244. total_lines *= te->frame_rate;
  245. vclks_line = (total_lines) ? vsync_clk_speed_hz / total_lines : 0;
  246. cfg |= BIT(19);
  247. if (te->hw_vsync_mode)
  248. cfg |= BIT(20);
  249. if (te->refx100) {
  250. vclks_line = vclks_line * te->frame_rate *
  251. 100 / te->refx100;
  252. } else {
  253. pr_warn("refx100 cannot be zero! Use 6000 as default\n");
  254. vclks_line = vclks_line * te->frame_rate *
  255. 100 / 6000;
  256. }
  257. cfg |= (vclks_line & VSYNC_COUNT_MASK);
  258. MDP3_REG_WRITE(MDP3_REG_SYNC_CONFIG_0 + dma_sel, cfg);
  259. MDP3_REG_WRITE(MDP3_REG_VSYNC_SEL, VSYNC_SELECT);
  260. MDP3_REG_WRITE(MDP3_REG_PRIMARY_VSYNC_INIT_VAL + dma_sel,
  261. te->vsync_init_val);
  262. MDP3_REG_WRITE(MDP3_REG_PRIMARY_RD_PTR_IRQ, te->rd_ptr_irq);
  263. MDP3_REG_WRITE(MDP3_REG_SYNC_THRESH_0 + dma_sel,
  264. ((te->sync_threshold_continue << VSYNC_THRESH_CONT_SHIFT) |
  265. te->sync_threshold_start));
  266. MDP3_REG_WRITE(MDP3_REG_PRIMARY_START_P0S + dma_sel, te->start_pos);
  267. MDP3_REG_WRITE(MDP3_REG_TEAR_CHECK_EN, te->tear_check_en);
  268. return 0;
  269. }
  270. static int mdp3_dmap_config(struct mdp3_dma *dma,
  271. struct mdp3_dma_source *source_config,
  272. struct mdp3_dma_output_config *output_config)
  273. {
  274. u32 dma_p_cfg_reg, dma_p_size, dma_p_out_xy;
  275. dma_p_cfg_reg = source_config->format << 25;
  276. if (output_config->dither_en)
  277. dma_p_cfg_reg |= BIT(24);
  278. dma_p_cfg_reg |= output_config->out_sel << 19;
  279. dma_p_cfg_reg |= output_config->bit_mask_polarity << 18;
  280. dma_p_cfg_reg |= output_config->color_components_flip << 14;
  281. dma_p_cfg_reg |= output_config->pack_pattern << 8;
  282. dma_p_cfg_reg |= output_config->pack_align << 7;
  283. dma_p_cfg_reg |= output_config->color_comp_out_bits;
  284. dma_p_size = source_config->width | (source_config->height << 16);
  285. dma_p_out_xy = source_config->x | (source_config->y << 16);
  286. MDP3_REG_WRITE(MDP3_REG_DMA_P_CONFIG, dma_p_cfg_reg);
  287. MDP3_REG_WRITE(MDP3_REG_DMA_P_SIZE, dma_p_size);
  288. MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)source_config->buf);
  289. MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_Y_STRIDE, source_config->stride);
  290. MDP3_REG_WRITE(MDP3_REG_DMA_P_OUT_XY, dma_p_out_xy);
  291. MDP3_REG_WRITE(MDP3_REG_DMA_P_FETCH_CFG, 0x40);
  292. dma->source_config = *source_config;
  293. dma->output_config = *output_config;
  294. mdp3_irq_enable(MDP3_INTR_LCDC_UNDERFLOW);
  295. mdp3_dma_callback_setup(dma);
  296. return 0;
  297. }
  298. static void mdp3_dmap_config_source(struct mdp3_dma *dma)
  299. {
  300. struct mdp3_dma_source *source_config = &dma->source_config;
  301. u32 dma_p_cfg_reg, dma_p_size;
  302. dma_p_cfg_reg = MDP3_REG_READ(MDP3_REG_DMA_P_CONFIG);
  303. dma_p_cfg_reg &= ~MDP3_DMA_IBUF_FORMAT_MASK;
  304. dma_p_cfg_reg |= source_config->format << 25;
  305. dma_p_cfg_reg &= ~MDP3_DMA_PACK_PATTERN_MASK;
  306. dma_p_cfg_reg |= dma->output_config.pack_pattern << 8;
  307. dma_p_size = source_config->width | (source_config->height << 16);
  308. MDP3_REG_WRITE(MDP3_REG_DMA_P_CONFIG, dma_p_cfg_reg);
  309. MDP3_REG_WRITE(MDP3_REG_DMA_P_SIZE, dma_p_size);
  310. MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_Y_STRIDE, source_config->stride);
  311. }
  312. static int mdp3_dmas_config(struct mdp3_dma *dma,
  313. struct mdp3_dma_source *source_config,
  314. struct mdp3_dma_output_config *output_config)
  315. {
  316. u32 dma_s_cfg_reg, dma_s_size, dma_s_out_xy;
  317. dma_s_cfg_reg = source_config->format << 25;
  318. if (output_config->dither_en)
  319. dma_s_cfg_reg |= BIT(24);
  320. dma_s_cfg_reg |= output_config->out_sel << 19;
  321. dma_s_cfg_reg |= output_config->bit_mask_polarity << 18;
  322. dma_s_cfg_reg |= output_config->color_components_flip << 14;
  323. dma_s_cfg_reg |= output_config->pack_pattern << 8;
  324. dma_s_cfg_reg |= output_config->pack_align << 7;
  325. dma_s_cfg_reg |= output_config->color_comp_out_bits;
  326. dma_s_size = source_config->width | (source_config->height << 16);
  327. dma_s_out_xy = source_config->x | (source_config->y << 16);
  328. MDP3_REG_WRITE(MDP3_REG_DMA_S_CONFIG, dma_s_cfg_reg);
  329. MDP3_REG_WRITE(MDP3_REG_DMA_S_SIZE, dma_s_size);
  330. MDP3_REG_WRITE(MDP3_REG_DMA_S_IBUF_ADDR, (u32)source_config->buf);
  331. MDP3_REG_WRITE(MDP3_REG_DMA_S_IBUF_Y_STRIDE, source_config->stride);
  332. MDP3_REG_WRITE(MDP3_REG_DMA_S_OUT_XY, dma_s_out_xy);
  333. MDP3_REG_WRITE(MDP3_REG_SECONDARY_RD_PTR_IRQ, 0x10);
  334. dma->source_config = *source_config;
  335. dma->output_config = *output_config;
  336. mdp3_dma_callback_setup(dma);
  337. return 0;
  338. }
  339. static void mdp3_dmas_config_source(struct mdp3_dma *dma)
  340. {
  341. struct mdp3_dma_source *source_config = &dma->source_config;
  342. u32 dma_s_cfg_reg, dma_s_size;
  343. dma_s_cfg_reg = MDP3_REG_READ(MDP3_REG_DMA_S_CONFIG);
  344. dma_s_cfg_reg &= ~MDP3_DMA_IBUF_FORMAT_MASK;
  345. dma_s_cfg_reg |= source_config->format << 25;
  346. dma_s_size = source_config->width | (source_config->height << 16);
  347. MDP3_REG_WRITE(MDP3_REG_DMA_S_CONFIG, dma_s_cfg_reg);
  348. MDP3_REG_WRITE(MDP3_REG_DMA_S_SIZE, dma_s_size);
  349. MDP3_REG_WRITE(MDP3_REG_DMA_S_IBUF_Y_STRIDE, source_config->stride);
  350. }
  351. static int mdp3_dmap_cursor_config(struct mdp3_dma *dma,
  352. struct mdp3_dma_cursor *cursor)
  353. {
  354. u32 cursor_size, cursor_pos, blend_param, trans_mask;
  355. cursor_size = cursor->width | (cursor->height << 16);
  356. cursor_pos = cursor->x | (cursor->y << 16);
  357. trans_mask = 0;
  358. if (cursor->blend_config.mode == MDP3_DMA_CURSOR_BLEND_CONSTANT_ALPHA) {
  359. blend_param = cursor->blend_config.constant_alpha << 24;
  360. } else if (cursor->blend_config.mode ==
  361. MDP3_DMA_CURSOR_BLEND_COLOR_KEYING) {
  362. blend_param = cursor->blend_config.transparent_color;
  363. trans_mask = cursor->blend_config.transparency_mask;
  364. } else {
  365. blend_param = 0;
  366. }
  367. MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_FORMAT, cursor->format);
  368. MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_SIZE, cursor_size);
  369. MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_BUF_ADDR, (u32)cursor->buf);
  370. MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_POS, cursor_pos);
  371. MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_BLEND_CONFIG,
  372. cursor->blend_config.mode);
  373. MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_BLEND_PARAM, blend_param);
  374. MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_BLEND_TRANS_MASK, trans_mask);
  375. dma->cursor = *cursor;
  376. return 0;
  377. }
  378. static void mdp3_ccs_update(struct mdp3_dma *dma)
  379. {
  380. u32 cc_config;
  381. int updated = 0;
  382. cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
  383. if (dma->ccs_config.ccs_dirty) {
  384. cc_config &= DMA_CCS_CONFIG_MASK;
  385. if (dma->ccs_config.ccs_enable)
  386. cc_config |= BIT(3);
  387. else
  388. cc_config &= ~BIT(3);
  389. cc_config |= dma->ccs_config.ccs_sel << 5;
  390. cc_config |= dma->ccs_config.pre_bias_sel << 6;
  391. cc_config |= dma->ccs_config.post_bias_sel << 7;
  392. cc_config |= dma->ccs_config.pre_limit_sel << 8;
  393. cc_config |= dma->ccs_config.post_limit_sel << 9;
  394. dma->ccs_config.ccs_dirty = false;
  395. updated = 1;
  396. }
  397. if (dma->lut_config.lut_dirty) {
  398. cc_config &= DMA_LUT_CONFIG_MASK;
  399. cc_config |= dma->lut_config.lut_enable;
  400. cc_config |= dma->lut_config.lut_position << 4;
  401. cc_config |= dma->lut_config.lut_sel << 10;
  402. dma->lut_config.lut_dirty = false;
  403. updated = 1;
  404. }
  405. if (updated) {
  406. MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
  407. /* Make sure ccs configuration update is done before continuing
  408. with the DMA transfer */
  409. wmb();
  410. }
  411. }
  412. static int mdp3_dmap_ccs_config(struct mdp3_dma *dma,
  413. struct mdp3_dma_color_correct_config *config,
  414. struct mdp3_dma_ccs *ccs)
  415. {
  416. int i;
  417. u32 addr;
  418. if (!ccs)
  419. return -EINVAL;
  420. if (config->ccs_enable) {
  421. addr = MDP3_REG_DMA_P_CSC_MV1;
  422. if (config->ccs_sel)
  423. addr = MDP3_REG_DMA_P_CSC_MV2;
  424. for (i = 0; i < 9; i++) {
  425. MDP3_REG_WRITE(addr, ccs->mv[i]);
  426. addr += 4;
  427. }
  428. addr = MDP3_REG_DMA_P_CSC_PRE_BV1;
  429. if (config->pre_bias_sel)
  430. addr = MDP3_REG_DMA_P_CSC_PRE_BV2;
  431. for (i = 0; i < 3; i++) {
  432. MDP3_REG_WRITE(addr, ccs->pre_bv[i]);
  433. addr += 4;
  434. }
  435. addr = MDP3_REG_DMA_P_CSC_POST_BV1;
  436. if (config->post_bias_sel)
  437. addr = MDP3_REG_DMA_P_CSC_POST_BV2;
  438. for (i = 0; i < 3; i++) {
  439. MDP3_REG_WRITE(addr, ccs->post_bv[i]);
  440. addr += 4;
  441. }
  442. addr = MDP3_REG_DMA_P_CSC_PRE_LV1;
  443. if (config->pre_limit_sel)
  444. addr = MDP3_REG_DMA_P_CSC_PRE_LV2;
  445. for (i = 0; i < 6; i++) {
  446. MDP3_REG_WRITE(addr, ccs->pre_lv[i]);
  447. addr += 4;
  448. }
  449. addr = MDP3_REG_DMA_P_CSC_POST_LV1;
  450. if (config->post_limit_sel)
  451. addr = MDP3_REG_DMA_P_CSC_POST_LV2;
  452. for (i = 0; i < 6; i++) {
  453. MDP3_REG_WRITE(addr, ccs->post_lv[i]);
  454. addr += 4;
  455. }
  456. }
  457. dma->ccs_config = *config;
  458. if (dma->output_config.out_sel != MDP3_DMA_OUTPUT_SEL_DSI_CMD)
  459. mdp3_ccs_update(dma);
  460. return 0;
  461. }
  462. static int mdp3_dmap_lut_config(struct mdp3_dma *dma,
  463. struct mdp3_dma_lut_config *config,
  464. struct mdp3_dma_lut *lut)
  465. {
  466. u32 addr, color;
  467. int i;
  468. if (config->lut_enable && lut) {
  469. addr = MDP3_REG_DMA_P_CSC_LUT1;
  470. if (config->lut_sel)
  471. addr = MDP3_REG_DMA_P_CSC_LUT2;
  472. for (i = 0; i < MDP_LUT_SIZE; i++) {
  473. color = lut->color0_lut[i] & 0xff;
  474. color |= (lut->color1_lut[i] & 0xff) << 8;
  475. color |= (lut->color2_lut[i] & 0xff) << 16;
  476. MDP3_REG_WRITE(addr, color);
  477. addr += 4;
  478. }
  479. }
  480. dma->lut_config = *config;
  481. if (dma->output_config.out_sel != MDP3_DMA_OUTPUT_SEL_DSI_CMD)
  482. mdp3_ccs_update(dma);
  483. return 0;
  484. }
  485. static int mdp3_dmap_histo_config(struct mdp3_dma *dma,
  486. struct mdp3_dma_histogram_config *histo_config)
  487. {
  488. unsigned long flag;
  489. u32 histo_bit_mask = 0, histo_control = 0;
  490. u32 histo_isr_mask = MDP3_DMA_P_HIST_INTR_HIST_DONE_BIT |
  491. MDP3_DMA_P_HIST_INTR_RESET_DONE_BIT;
  492. spin_lock_irqsave(&dma->histo_lock, flag);
  493. if (histo_config->bit_mask_polarity)
  494. histo_bit_mask = BIT(31);
  495. histo_bit_mask |= histo_config->bit_mask;
  496. if (histo_config->auto_clear_en)
  497. histo_control = BIT(0);
  498. MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_FRAME_CNT,
  499. histo_config->frame_count);
  500. MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_BIT_MASK, histo_bit_mask);
  501. MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_CONTROL, histo_control);
  502. MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, histo_isr_mask);
  503. spin_unlock_irqrestore(&dma->histo_lock, flag);
  504. dma->histogram_config = *histo_config;
  505. return 0;
  506. }
  507. static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf,
  508. struct mdp3_intf *intf)
  509. {
  510. unsigned long flag;
  511. int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
  512. int rc = 0;
  513. ATRACE_BEGIN(__func__);
  514. pr_debug("mdp3_dmap_update\n");
  515. if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
  516. cb_type = MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
  517. if (intf->active) {
  518. ATRACE_BEGIN("mdp3_wait_for_dma_comp");
  519. rc = wait_for_completion_timeout(&dma->dma_comp,
  520. KOFF_TIMEOUT);
  521. if (rc <= 0) {
  522. WARN(1, "cmd kickoff timed out (%d)\n", rc);
  523. rc = -1;
  524. }
  525. ATRACE_END("mdp3_wait_for_dma_comp");
  526. }
  527. }
  528. if (dma->update_src_cfg) {
  529. if (dma->output_config.out_sel ==
  530. MDP3_DMA_OUTPUT_SEL_DSI_VIDEO && intf->active)
  531. pr_err("configuring dma source while dma is active\n");
  532. dma->dma_config_source(dma);
  533. dma->update_src_cfg = false;
  534. }
  535. spin_lock_irqsave(&dma->dma_lock, flag);
  536. MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
  537. dma->source_config.buf = buf;
  538. if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
  539. mdp3_ccs_update(dma);
  540. MDP3_REG_WRITE(MDP3_REG_DMA_P_START, 1);
  541. }
  542. if (!intf->active) {
  543. pr_debug("mdp3_dmap_update start interface\n");
  544. intf->start(intf);
  545. }
  546. mb();
  547. dma->vsync_status = MDP3_REG_READ(MDP3_REG_INTR_STATUS) &
  548. (1 << MDP3_INTR_LCDC_START_OF_FRAME);
  549. init_completion(&dma->vsync_comp);
  550. spin_unlock_irqrestore(&dma->dma_lock, flag);
  551. mdp3_dma_callback_enable(dma, cb_type);
  552. pr_debug("mdp3_dmap_update wait for vsync_comp in\n");
  553. if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) {
  554. ATRACE_BEGIN("mdp3_wait_for_vsync_comp");
  555. rc = wait_for_completion_timeout(&dma->vsync_comp,
  556. KOFF_TIMEOUT);
  557. if (rc <= 0)
  558. rc = -1;
  559. ATRACE_END("mdp3_wait_for_vsync_comp");
  560. }
  561. pr_debug("mdp3_dmap_update wait for vsync_comp out\n");
  562. ATRACE_END(__func__);
  563. return rc;
  564. }
  565. static int mdp3_dmas_update(struct mdp3_dma *dma, void *buf,
  566. struct mdp3_intf *intf)
  567. {
  568. unsigned long flag;
  569. int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
  570. if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
  571. cb_type = MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
  572. if (intf->active)
  573. wait_for_completion_killable(&dma->dma_comp);
  574. }
  575. spin_lock_irqsave(&dma->dma_lock, flag);
  576. MDP3_REG_WRITE(MDP3_REG_DMA_S_IBUF_ADDR, (u32)buf);
  577. dma->source_config.buf = buf;
  578. if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD)
  579. MDP3_REG_WRITE(MDP3_REG_DMA_S_START, 1);
  580. if (!intf->active) {
  581. pr_debug("mdp3_dmap_update start interface\n");
  582. intf->start(intf);
  583. }
  584. wmb();
  585. init_completion(&dma->vsync_comp);
  586. spin_unlock_irqrestore(&dma->dma_lock, flag);
  587. mdp3_dma_callback_enable(dma, cb_type);
  588. if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)
  589. wait_for_completion_killable(&dma->vsync_comp);
  590. return 0;
  591. }
  592. static int mdp3_dmap_cursor_update(struct mdp3_dma *dma, int x, int y)
  593. {
  594. u32 cursor_pos;
  595. cursor_pos = x | (y << 16);
  596. MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_POS, cursor_pos);
  597. dma->cursor.x = x;
  598. dma->cursor.y = y;
  599. return 0;
  600. }
  601. static int mdp3_dmap_histo_get(struct mdp3_dma *dma)
  602. {
  603. int i, state, timeout, ret;
  604. u32 addr;
  605. unsigned long flag;
  606. spin_lock_irqsave(&dma->histo_lock, flag);
  607. state = dma->histo_state;
  608. spin_unlock_irqrestore(&dma->histo_lock, flag);
  609. if (state != MDP3_DMA_HISTO_STATE_START &&
  610. state != MDP3_DMA_HISTO_STATE_READY) {
  611. pr_err("mdp3_dmap_histo_get invalid state %d\n", state);
  612. return -EINVAL;
  613. }
  614. timeout = HIST_WAIT_TIMEOUT(dma->histogram_config.frame_count);
  615. ret = wait_for_completion_killable_timeout(&dma->histo_comp, timeout);
  616. if (ret == 0) {
  617. pr_debug("mdp3_dmap_histo_get time out\n");
  618. ret = -ETIMEDOUT;
  619. } else if (ret < 0) {
  620. pr_err("mdp3_dmap_histo_get interrupted\n");
  621. }
  622. if (ret < 0)
  623. return ret;
  624. if (dma->histo_state != MDP3_DMA_HISTO_STATE_READY) {
  625. pr_debug("mdp3_dmap_histo_get after dma shut down\n");
  626. return -EPERM;
  627. }
  628. addr = MDP3_REG_DMA_P_HIST_R_DATA;
  629. for (i = 0; i < MDP_HISTOGRAM_BIN_NUM; i++) {
  630. dma->histo_data.r_data[i] = MDP3_REG_READ(addr);
  631. addr += 4;
  632. }
  633. addr = MDP3_REG_DMA_P_HIST_G_DATA;
  634. for (i = 0; i < MDP_HISTOGRAM_BIN_NUM; i++) {
  635. dma->histo_data.g_data[i] = MDP3_REG_READ(addr);
  636. addr += 4;
  637. }
  638. addr = MDP3_REG_DMA_P_HIST_B_DATA;
  639. for (i = 0; i < MDP_HISTOGRAM_BIN_NUM; i++) {
  640. dma->histo_data.b_data[i] = MDP3_REG_READ(addr);
  641. addr += 4;
  642. }
  643. dma->histo_data.extra[0] =
  644. MDP3_REG_READ(MDP3_REG_DMA_P_HIST_EXTRA_INFO_0);
  645. dma->histo_data.extra[1] =
  646. MDP3_REG_READ(MDP3_REG_DMA_P_HIST_EXTRA_INFO_1);
  647. spin_lock_irqsave(&dma->histo_lock, flag);
  648. INIT_COMPLETION(dma->histo_comp);
  649. MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_START, 1);
  650. wmb();
  651. dma->histo_state = MDP3_DMA_HISTO_STATE_START;
  652. spin_unlock_irqrestore(&dma->histo_lock, flag);
  653. return 0;
  654. }
  655. static int mdp3_dmap_histo_start(struct mdp3_dma *dma)
  656. {
  657. unsigned long flag;
  658. if (dma->histo_state != MDP3_DMA_HISTO_STATE_IDLE)
  659. return -EINVAL;
  660. spin_lock_irqsave(&dma->histo_lock, flag);
  661. INIT_COMPLETION(dma->histo_comp);
  662. MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_START, 1);
  663. wmb();
  664. dma->histo_state = MDP3_DMA_HISTO_STATE_START;
  665. spin_unlock_irqrestore(&dma->histo_lock, flag);
  666. mdp3_dma_callback_enable(dma, MDP3_DMA_CALLBACK_TYPE_HIST_DONE);
  667. return 0;
  668. }
  669. static int mdp3_dmap_histo_reset(struct mdp3_dma *dma)
  670. {
  671. unsigned long flag;
  672. int ret;
  673. spin_lock_irqsave(&dma->histo_lock, flag);
  674. INIT_COMPLETION(dma->histo_comp);
  675. mdp3_dma_clk_auto_gating(dma, 0);
  676. MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, BIT(0)|BIT(1));
  677. MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_RESET_SEQ_START, 1);
  678. wmb();
  679. dma->histo_state = MDP3_DMA_HISTO_STATE_RESET;
  680. spin_unlock_irqrestore(&dma->histo_lock, flag);
  681. mdp3_dma_callback_enable(dma, MDP3_DMA_CALLBACK_TYPE_HIST_RESET_DONE);
  682. ret = wait_for_completion_killable_timeout(&dma->histo_comp,
  683. msecs_to_jiffies(DMA_HISTO_RESET_TIMEOUT_MS));
  684. if (ret == 0) {
  685. pr_err("mdp3_dmap_histo_reset time out\n");
  686. ret = -ETIMEDOUT;
  687. } else if (ret < 0) {
  688. pr_err("mdp3_dmap_histo_reset interrupted\n");
  689. } else {
  690. ret = 0;
  691. }
  692. mdp3_dma_callback_disable(dma, MDP3_DMA_CALLBACK_TYPE_HIST_RESET_DONE);
  693. mdp3_dma_clk_auto_gating(dma, 1);
  694. return ret;
  695. }
  696. static int mdp3_dmap_histo_stop(struct mdp3_dma *dma)
  697. {
  698. unsigned long flag;
  699. int cb_type = MDP3_DMA_CALLBACK_TYPE_HIST_RESET_DONE |
  700. MDP3_DMA_CALLBACK_TYPE_HIST_DONE;
  701. spin_lock_irqsave(&dma->histo_lock, flag);
  702. MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_CANCEL_REQ, 1);
  703. MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, 0);
  704. wmb();
  705. dma->histo_state = MDP3_DMA_HISTO_STATE_IDLE;
  706. complete(&dma->histo_comp);
  707. spin_unlock_irqrestore(&dma->histo_lock, flag);
  708. mdp3_dma_callback_disable(dma, cb_type);
  709. return 0;
  710. }
  711. static int mdp3_dmap_histo_op(struct mdp3_dma *dma, u32 op)
  712. {
  713. int ret;
  714. switch (op) {
  715. case MDP3_DMA_HISTO_OP_START:
  716. ret = mdp3_dmap_histo_start(dma);
  717. break;
  718. case MDP3_DMA_HISTO_OP_STOP:
  719. case MDP3_DMA_HISTO_OP_CANCEL:
  720. ret = mdp3_dmap_histo_stop(dma);
  721. break;
  722. case MDP3_DMA_HISTO_OP_RESET:
  723. ret = mdp3_dmap_histo_reset(dma);
  724. break;
  725. default:
  726. ret = -EINVAL;
  727. }
  728. return ret;
  729. }
  730. static int mdp3_dma_start(struct mdp3_dma *dma, struct mdp3_intf *intf)
  731. {
  732. unsigned long flag;
  733. int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
  734. u32 dma_start_offset = MDP3_REG_DMA_P_START;
  735. if (dma->dma_sel == MDP3_DMA_P)
  736. dma_start_offset = MDP3_REG_DMA_P_START;
  737. else if (dma->dma_sel == MDP3_DMA_S)
  738. dma_start_offset = MDP3_REG_DMA_S_START;
  739. else
  740. return -EINVAL;
  741. spin_lock_irqsave(&dma->dma_lock, flag);
  742. if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
  743. cb_type |= MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
  744. MDP3_REG_WRITE(dma_start_offset, 1);
  745. }
  746. intf->start(intf);
  747. wmb();
  748. init_completion(&dma->vsync_comp);
  749. spin_unlock_irqrestore(&dma->dma_lock, flag);
  750. mdp3_dma_callback_enable(dma, cb_type);
  751. pr_debug("mdp3_dma_start wait for vsync_comp in\n");
  752. wait_for_completion_killable(&dma->vsync_comp);
  753. pr_debug("mdp3_dma_start wait for vsync_comp out\n");
  754. return 0;
  755. }
  756. static int mdp3_dma_stop(struct mdp3_dma *dma, struct mdp3_intf *intf)
  757. {
  758. int ret = 0;
  759. u32 status, display_status_bit;
  760. if (dma->dma_sel == MDP3_DMA_P)
  761. display_status_bit = BIT(6);
  762. else if (dma->dma_sel == MDP3_DMA_S)
  763. display_status_bit = BIT(7);
  764. else
  765. return -EINVAL;
  766. if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)
  767. display_status_bit |= BIT(11);
  768. intf->stop(intf);
  769. ret = readl_poll_timeout((mdp3_res->mdp_base + MDP3_REG_DISPLAY_STATUS),
  770. status,
  771. ((status & display_status_bit) == 0),
  772. DMA_STOP_POLL_SLEEP_US,
  773. DMA_STOP_POLL_TIMEOUT_US);
  774. mdp3_dma_callback_disable(dma, MDP3_DMA_CALLBACK_TYPE_VSYNC |
  775. MDP3_DMA_CALLBACK_TYPE_DMA_DONE);
  776. mdp3_irq_disable(MDP3_INTR_LCDC_UNDERFLOW);
  777. MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, 0);
  778. MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, 0xfffffff);
  779. init_completion(&dma->dma_comp);
  780. dma->vsync_client.handler = NULL;
  781. return ret;
  782. }
  783. int mdp3_dma_init(struct mdp3_dma *dma)
  784. {
  785. int ret = 0;
  786. pr_debug("mdp3_dma_init\n");
  787. switch (dma->dma_sel) {
  788. case MDP3_DMA_P:
  789. dma->dma_config = mdp3_dmap_config;
  790. dma->dma_sync_config = mdp3_dma_sync_config;
  791. dma->dma_config_source = mdp3_dmap_config_source;
  792. dma->config_cursor = mdp3_dmap_cursor_config;
  793. dma->config_ccs = mdp3_dmap_ccs_config;
  794. dma->config_histo = mdp3_dmap_histo_config;
  795. dma->config_lut = mdp3_dmap_lut_config;
  796. dma->update = mdp3_dmap_update;
  797. dma->update_cursor = mdp3_dmap_cursor_update;
  798. dma->get_histo = mdp3_dmap_histo_get;
  799. dma->histo_op = mdp3_dmap_histo_op;
  800. dma->vsync_enable = mdp3_dma_vsync_enable;
  801. dma->dma_done_notifier = mdp3_dma_done_notifier;
  802. dma->start = mdp3_dma_start;
  803. dma->stop = mdp3_dma_stop;
  804. break;
  805. case MDP3_DMA_S:
  806. dma->dma_config = mdp3_dmas_config;
  807. dma->dma_sync_config = mdp3_dma_sync_config;
  808. dma->dma_config_source = mdp3_dmas_config_source;
  809. dma->config_cursor = NULL;
  810. dma->config_ccs = NULL;
  811. dma->config_histo = NULL;
  812. dma->config_lut = NULL;
  813. dma->update = mdp3_dmas_update;
  814. dma->update_cursor = NULL;
  815. dma->get_histo = NULL;
  816. dma->histo_op = NULL;
  817. dma->vsync_enable = mdp3_dma_vsync_enable;
  818. dma->start = mdp3_dma_start;
  819. dma->stop = mdp3_dma_stop;
  820. break;
  821. case MDP3_DMA_E:
  822. default:
  823. ret = -ENODEV;
  824. break;
  825. }
  826. spin_lock_init(&dma->dma_lock);
  827. spin_lock_init(&dma->histo_lock);
  828. init_completion(&dma->vsync_comp);
  829. init_completion(&dma->dma_comp);
  830. init_completion(&dma->histo_comp);
  831. dma->vsync_client.handler = NULL;
  832. dma->vsync_client.arg = NULL;
  833. dma->histo_state = MDP3_DMA_HISTO_STATE_IDLE;
  834. dma->update_src_cfg = false;
  835. memset(&dma->cursor, 0, sizeof(dma->cursor));
  836. memset(&dma->ccs_config, 0, sizeof(dma->ccs_config));
  837. memset(&dma->histogram_config, 0, sizeof(dma->histogram_config));
  838. return ret;
  839. }
  840. int lcdc_config(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
  841. {
  842. u32 temp;
  843. struct mdp3_video_intf_cfg *v = &cfg->video;
  844. temp = v->hsync_pulse_width | (v->hsync_period << 16);
  845. MDP3_REG_WRITE(MDP3_REG_LCDC_HSYNC_CTL, temp);
  846. MDP3_REG_WRITE(MDP3_REG_LCDC_VSYNC_PERIOD, v->vsync_period);
  847. MDP3_REG_WRITE(MDP3_REG_LCDC_VSYNC_PULSE_WIDTH, v->vsync_pulse_width);
  848. temp = v->display_start_x | (v->display_end_x << 16);
  849. MDP3_REG_WRITE(MDP3_REG_LCDC_DISPLAY_HCTL, temp);
  850. MDP3_REG_WRITE(MDP3_REG_LCDC_DISPLAY_V_START, v->display_start_y);
  851. MDP3_REG_WRITE(MDP3_REG_LCDC_DISPLAY_V_END, v->display_end_y);
  852. temp = v->active_start_x | (v->active_end_x);
  853. if (v->active_h_enable)
  854. temp |= BIT(31);
  855. MDP3_REG_WRITE(MDP3_REG_LCDC_ACTIVE_HCTL, temp);
  856. MDP3_REG_WRITE(MDP3_REG_LCDC_ACTIVE_V_START, v->active_start_y);
  857. MDP3_REG_WRITE(MDP3_REG_LCDC_ACTIVE_V_END, v->active_end_y);
  858. MDP3_REG_WRITE(MDP3_REG_LCDC_HSYNC_SKEW, v->hsync_skew);
  859. temp = 0;
  860. if (!v->hsync_polarity)
  861. temp = BIT(0);
  862. if (!v->vsync_polarity)
  863. temp = BIT(1);
  864. if (!v->de_polarity)
  865. temp = BIT(2);
  866. MDP3_REG_WRITE(MDP3_REG_LCDC_CTL_POLARITY, temp);
  867. return 0;
  868. }
  869. int lcdc_start(struct mdp3_intf *intf)
  870. {
  871. MDP3_REG_WRITE(MDP3_REG_LCDC_EN, BIT(0));
  872. wmb();
  873. intf->active = true;
  874. return 0;
  875. }
  876. int lcdc_stop(struct mdp3_intf *intf)
  877. {
  878. MDP3_REG_WRITE(MDP3_REG_LCDC_EN, 0);
  879. wmb();
  880. intf->active = false;
  881. return 0;
  882. }
  883. int dsi_video_config(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
  884. {
  885. u32 temp;
  886. struct mdp3_video_intf_cfg *v = &cfg->video;
  887. pr_debug("dsi_video_config\n");
  888. temp = v->hsync_pulse_width | (v->hsync_period << 16);
  889. MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_HSYNC_CTL, temp);
  890. MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_VSYNC_PERIOD, v->vsync_period);
  891. MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_VSYNC_PULSE_WIDTH,
  892. v->vsync_pulse_width);
  893. temp = v->display_start_x | (v->display_end_x << 16);
  894. MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_DISPLAY_HCTL, temp);
  895. MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_DISPLAY_V_START, v->display_start_y);
  896. MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_DISPLAY_V_END, v->display_end_y);
  897. temp = v->active_start_x | (v->active_end_x << 16);
  898. if (v->active_h_enable)
  899. temp |= BIT(31);
  900. MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_ACTIVE_HCTL, temp);
  901. temp = v->active_start_y;
  902. if (v->active_v_enable)
  903. temp |= BIT(31);
  904. MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_ACTIVE_V_START, temp);
  905. MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_ACTIVE_V_END, v->active_end_y);
  906. MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_HSYNC_SKEW, v->hsync_skew);
  907. temp = 0;
  908. if (!v->hsync_polarity)
  909. temp |= BIT(0);
  910. if (!v->vsync_polarity)
  911. temp |= BIT(1);
  912. if (!v->de_polarity)
  913. temp |= BIT(2);
  914. MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_CTL_POLARITY, temp);
  915. v->underflow_color |= 0x80000000;
  916. MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_UNDERFLOW_CTL, v->underflow_color);
  917. return 0;
  918. }
  919. int dsi_video_start(struct mdp3_intf *intf)
  920. {
  921. pr_debug("dsi_video_start\n");
  922. MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_EN, BIT(0));
  923. wmb();
  924. intf->active = true;
  925. return 0;
  926. }
  927. int dsi_video_stop(struct mdp3_intf *intf)
  928. {
  929. pr_debug("dsi_video_stop\n");
  930. MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_EN, 0);
  931. wmb();
  932. intf->active = false;
  933. return 0;
  934. }
  935. int dsi_cmd_config(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
  936. {
  937. u32 id_map = 0;
  938. u32 trigger_en = 0;
  939. if (cfg->dsi_cmd.primary_dsi_cmd_id)
  940. id_map = BIT(0);
  941. if (cfg->dsi_cmd.secondary_dsi_cmd_id)
  942. id_map = BIT(4);
  943. if (cfg->dsi_cmd.dsi_cmd_tg_intf_sel)
  944. trigger_en = BIT(4);
  945. MDP3_REG_WRITE(MDP3_REG_DSI_CMD_MODE_ID_MAP, id_map);
  946. MDP3_REG_WRITE(MDP3_REG_DSI_CMD_MODE_TRIGGER_EN, trigger_en);
  947. return 0;
  948. }
  949. int dsi_cmd_start(struct mdp3_intf *intf)
  950. {
  951. intf->active = true;
  952. return 0;
  953. }
  954. int dsi_cmd_stop(struct mdp3_intf *intf)
  955. {
  956. intf->active = false;
  957. return 0;
  958. }
  959. int mdp3_intf_init(struct mdp3_intf *intf)
  960. {
  961. switch (intf->cfg.type) {
  962. case MDP3_DMA_OUTPUT_SEL_LCDC:
  963. intf->config = lcdc_config;
  964. intf->start = lcdc_start;
  965. intf->stop = lcdc_stop;
  966. break;
  967. case MDP3_DMA_OUTPUT_SEL_DSI_VIDEO:
  968. intf->config = dsi_video_config;
  969. intf->start = dsi_video_start;
  970. intf->stop = dsi_video_stop;
  971. break;
  972. case MDP3_DMA_OUTPUT_SEL_DSI_CMD:
  973. intf->config = dsi_cmd_config;
  974. intf->start = dsi_cmd_start;
  975. intf->stop = dsi_cmd_stop;
  976. break;
  977. default:
  978. return -EINVAL;
  979. }
  980. return 0;
  981. }