2 * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Based on MXC EPDC Driver, Freescale Semiconductor, Inc. All Rights Reserved.
23 #include "mxc_spdc_fb.h"
29 #define SPDC_DEFAULT_TEMP 30
30 #define TEMP_NO_SET 0xFF
31 #define POWER_STATE_OFF 0
32 #define POWER_STATE_ON 1
33 #define POWER_READY_OFF false
34 #define POWER_READY_ON true
36 #define INIT_UPDATE_MARKER 0x12345678
37 #define PAN_UPDATE_MARKER 0x12345679
39 #define SPDC_MAX_NUM_UPDATES 32
40 #define SPDC_MAX_NUM_BUFFERS 2
41 #define SPDC_MAX_NUM_PREPROCESS 15
42 #define NUM_SCREENS_MIN 2
43 #define SPDC_DEFAULT_BPP 16
45 mxc_spdc_t *g_fb_data;
47 static int mxc_spdc_fb_send_update(struct mxcfb_update_data *upd_data,
48 struct fb_info *info);
49 static int mxc_spdc_fb_wait_update_complete(struct mxcfb_update_marker_data
50 *marker_data, struct fb_info *info);
52 static const struct mxc_spdc_resolution_map_para spdc_gray_res_map[] = {
53 /*define Gray Mode resolution mapping*/
54 {0x18, 600, 800, PORTRAIT},
55 {0x19, 768, 1024, PORTRAIT},
56 {0x1a, 0, 0, RESERVED},
57 {0x1b, 600, 1024, PORTRAIT},
58 {0x1c, 825, 1200, PORTRAIT},
59 {0x1d, 1024, 1280, PORTRAIT},
60 {0x1e, 1200, 1600, PORTRAIT},
61 {0x10, 800, 1024, PORTRAIT},
62 {0x11, 825, 1280, PORTRAIT},
63 {0x12, 800, 1280, PORTRAIT},
64 {0x13, 768, 1280, PORTRAIT},
65 {0x14, 960, 1280, PORTRAIT},
66 {0x0, 800, 600, LANDSCAPE},
67 {0x1, 1024, 768, LANDSCAPE},
68 {0x2, 0, 0, RESERVED},
69 {0x3, 1024, 600, LANDSCAPE},
70 {0x4, 1200, 825, LANDSCAPE},
71 {0x5, 1280, 1024, LANDSCAPE},
72 {0x6, 1600, 1200, LANDSCAPE},
73 {0x7, 1024, 800, LANDSCAPE},
74 {0x8, 1280, 825, LANDSCAPE},
75 {0x9, 1280, 800, LANDSCAPE},
76 {0xa, 1280, 768, LANDSCAPE},
77 {0xb, 1280, 960, LANDSCAPE},
78 {0xFFFF, 800, 600, LANDSCAPE},
81 static const struct mxc_spdc_resolution_map_para spdc_rgbw_res_map[] = {
82 /*define RGBW Mode resolution mapping*/
83 {0x18, 300, 400, PORTRAIT},
84 {0x19, 384, 512, PORTRAIT},
85 {0x1a, 0, 0, RESERVED},
86 {0x1b, 300, 512, PORTRAIT},
87 {0x1c, 0, 0, RESERVED},
88 {0x1d, 512, 640, PORTRAIT},
89 {0x1e, 600, 800, PORTRAIT},
90 {0x10, 400, 512, PORTRAIT},
91 {0x11, 0, 0, RESERVED},
92 {0x12, 400, 640, PORTRAIT},
93 {0x13, 384, 640, PORTRAIT},
94 {0x14, 480, 640, PORTRAIT},
95 {0x0, 400, 300, LANDSCAPE},
96 {0x1, 512, 384, LANDSCAPE},
97 {0x2, 0, 0, RESERVED},
98 {0x3, 512, 300, LANDSCAPE},
99 {0x4, 0, 0, RESERVED},
100 {0x5, 640, 512, LANDSCAPE},
101 {0x6, 800, 600, LANDSCAPE},
102 {0x7, 512, 400, LANDSCAPE},
103 {0x8, 0, 0, RESERVED},
104 {0x9, 640, 400, LANDSCAPE},
105 {0xa, 640, 384, LANDSCAPE},
106 {0xb, 640, 480, LANDSCAPE},
107 {0xFFFF, 400, 300, LANDSCAPE},
110 static void get_panel_init_set(struct imx_spdc_panel_init_set*
113 *val = panel_set->yoe_pol |
114 (panel_set->dual_gate << 1) |
115 (panel_set->ud << 7) |
116 (panel_set->rl << 8) |
117 (panel_set->data_filter_n << 9) |
118 (panel_set->power_ready << 10) |
119 (panel_set->rgbw_mode_enable << 11) |
120 (panel_set->hburst_len_en << 13) |
121 ((panel_set->resolution & 0x1F) << 2);
124 static inline void spdc_intr_enable(mxc_spdc_t *fb_data, u32 int_type)
128 status = __raw_readl(fb_data->hwp + SPDC_INT_ENABLE);
129 status |= (int_type & SPDC_IRQ_ALL_MASK);
130 __raw_writel(status, fb_data->hwp + SPDC_INT_ENABLE);
133 static bool spdc_is_update_finish(mxc_spdc_t *fb_data)
135 u32 val = __raw_readl(fb_data->hwp + SPDC_INT_STA_CLR);
136 bool is_finish = (val & SPDC_IRQ_STA_FRAME_UPDATE) ? true : false;
141 static int spdc_get_intr_stat(mxc_spdc_t *fb_data)
143 u32 status = __raw_readl(fb_data->hwp + SPDC_INT_STA_CLR);
148 spdc_intr_stat_clear(mxc_spdc_t *fb_data, u32 int_type)
150 /* write 1 to clear status */
151 u32 status = (int_type & SPDC_IRQ_STA_ALL_MASK);
152 __raw_writel(status, fb_data->hwp + SPDC_INT_STA_CLR);
155 static inline void spdc_set_nextbuf_addr(mxc_spdc_t *fb_data)
157 u32 addr = fb_data->fresh_param.buf_addr.next_buf_phys_addr;
158 __raw_writel(addr, fb_data->hwp + SPDC_NEXT_BUF);
159 dev_dbg(fb_data->dev, "add: 0x%x\n", addr);
162 static inline void spdc_set_curbuf_addr(mxc_spdc_t *fb_data)
164 u32 addr = fb_data->fresh_param.buf_addr.cur_buf_phys_addr;
165 __raw_writel(addr, fb_data->hwp + SPDC_CURRENT_BUF);
168 static inline void spdc_set_prebuf_addr(mxc_spdc_t *fb_data)
170 u32 addr = fb_data->fresh_param.buf_addr.pre_buf_phys_addr;
171 __raw_writel(addr, fb_data->hwp + SPDC_PRE_BUF);
174 static inline void spdc_set_cntbuf_addr(mxc_spdc_t *fb_data)
176 u32 addr = fb_data->fresh_param.buf_addr.frm_cnt_buf_phys_addr;
177 __raw_writel(addr, fb_data->hwp + SPDC_CNT_BUF);
180 static inline void spdc_set_lutbuf_addr(mxc_spdc_t *fb_data)
182 u32 addr = fb_data->fresh_param.buf_addr.lut_buf_phys_addr;
183 __raw_writel(addr, fb_data->hwp + SPDC_LUT_BUF);
186 static inline void spdc_set_update_coord(mxc_spdc_t *fb_data)
188 u32 x = fb_data->fresh_param.update_region.left;
189 u32 y = fb_data->fresh_param.update_region.top;
196 dev_dbg(fb_data->dev, "x:%d, y:%d\n", x, y);
197 x = (u32)(((x & SPDC_UPDATE_X_Y_MAX_SIZE) << 16) |
198 (y & SPDC_UPDATE_X_Y_MAX_SIZE));
199 __raw_writel(x, fb_data->hwp + SPDC_UPDATA_X_Y);
202 static inline void spdc_set_update_dimensions(mxc_spdc_t *fb_data)
204 u32 w = fb_data->fresh_param.update_region.width;
205 u32 h = fb_data->fresh_param.update_region.height;
212 dev_dbg(fb_data->dev, "w:%d, h:%d\n", w, h);
213 w = (u32)(((w & SPDC_UPDATE_W_H_MAX_SIZE) << 16) |
214 (h & SPDC_UPDATE_W_H_MAX_SIZE));
215 __raw_writel(w, fb_data->hwp + SPDC_UPDATE_W_H);
218 static inline void spdc_set_update_temper(mxc_spdc_t *fb_data)
220 s8 temper = (s8)(fb_data->fresh_param.temper & 0xFF) << 1;
222 if (temper > -110 && temper < 200)
223 __raw_writel(temper, fb_data->hwp + SPDC_TEMP_INFO);
225 __raw_writel(SPDC_DEFAULT_TEMP, fb_data->hwp + SPDC_TEMP_INFO);
228 static inline void spdc_trigger_update(mxc_spdc_t *fb_data)
231 struct partial_refresh_param *fresh_param = &fb_data->fresh_param;
233 if ((fresh_param->wave_mode & SPDC_WAV_MODE_MASK) && fresh_param->flash)
234 val = SPDC_DISP_TRIGGER_FLASH;
238 val |= fresh_param->wave_mode << 1;
239 val |= SPDC_DISP_TRIGGER_ENABLE;
240 dev_dbg(fb_data->dev, "wave:%d\n", fresh_param->wave_mode);
241 __raw_writel(val, fb_data->hwp + SPDC_DISP_TRIGGER);
244 static bool is_lut_checksum_ok(mxc_spdc_t *fb_data)
248 status = __raw_readl(fb_data->hwp + SPDC_STATUS);
249 status &= SPDC_IRQ_STA_ERR;
251 return status ? true : false;
254 static void spdc_clk_gate(mxc_spdc_t *fb_data, bool enable)
257 __raw_writel(SPDC_SW_GATE_CLK_ENABLE,
258 fb_data->hwp + SPDC_SW_GATE_CLK);
260 __raw_writel(~SPDC_SW_GATE_CLK_ENABLE,
261 fb_data->hwp + SPDC_SW_GATE_CLK);
264 static int update_panel_init_set(mxc_spdc_t *fb_data)
269 get_panel_init_set(&fb_data->panel_set, &init_val);
270 dev_dbg(fb_data->dev, "panel init setting:%x\n", init_val);
272 __raw_writel(init_val, fb_data->hwp + SPDC_PANEL_INIT_SET);
274 /*wait init setting update finish*/
275 ret = wait_for_completion_timeout(&fb_data->init_finish,
276 msecs_to_jiffies(4000));
278 dev_err(fb_data->dev, "Timed out for init setting!\n");
283 static void spdc_panel_pwr_on(mxc_spdc_t *fb_data)
285 fb_data->panel_set.power_ready = POWER_READY_ON;
288 static void spdc_panel_pwr_down(mxc_spdc_t *fb_data)
290 fb_data->panel_set.power_ready = POWER_READY_OFF;
293 static void spdc_powerdown(mxc_spdc_t *fb_data)
295 mutex_lock(&fb_data->power_mutex);
297 /* If powering_down has been cleared, a powerup
298 * request is pre-empting this powerdown request.
300 if (!fb_data->powering_down
301 || (fb_data->power_state == POWER_STATE_OFF)) {
302 mutex_unlock(&fb_data->power_mutex);
306 dev_dbg(fb_data->dev, "spdc Powerdown\n");
308 /* Disable power to the AUO panel */
309 regulator_disable(fb_data->vcom_regulator);
310 regulator_disable(fb_data->display_regulator);
312 /*enable spdc clock gating*/
313 spdc_clk_gate(fb_data, true);
314 clk_disable(fb_data->spdc_clk_pix);
315 clk_disable(fb_data->spdc_clk_axi);
317 /* Disable pins used by SPDC (to prevent leakage current) */
318 if (fb_data->pdata->disable_pins)
319 fb_data->pdata->disable_pins();
321 /* turn off the V3p3 */
322 regulator_disable(fb_data->v3p3_regulator);
324 fb_data->power_state = POWER_STATE_OFF;
325 fb_data->powering_down = false;
326 spdc_panel_pwr_down(fb_data);
328 if (fb_data->wait_for_powerdown) {
329 fb_data->wait_for_powerdown = false;
330 complete(&fb_data->powerdown_compl);
333 mutex_unlock(&fb_data->power_mutex);
336 static void spdc_powerup(mxc_spdc_t *fb_data)
339 mutex_lock(&fb_data->power_mutex);
342 * If power down request is pending, clear
343 * powering_down to cancel the request.
345 if (fb_data->powering_down)
346 fb_data->powering_down = false;
348 if (fb_data->power_state == POWER_STATE_ON) {
349 mutex_unlock(&fb_data->power_mutex);
353 dev_dbg(fb_data->dev, "spdc Powerup\n");
355 /* Enable the v3p3 regulator */
356 ret = regulator_enable(fb_data->v3p3_regulator);
357 if (IS_ERR((void *)ret)) {
358 dev_err(fb_data->dev, "Unable to enable V3P3 regulator."
359 "err = 0x%x\n", ret);
360 mutex_unlock(&fb_data->power_mutex);
366 /* Enable pins used by SPDC */
367 if (fb_data->pdata->enable_pins)
368 fb_data->pdata->enable_pins();
370 /* Enable clocks to SPDC */
371 clk_enable(fb_data->spdc_clk_axi);
372 clk_enable(fb_data->spdc_clk_pix);
374 /*disable spdc gate*/
375 spdc_clk_gate(fb_data, false);
377 /* Enable power to the EPD panel */
378 ret = regulator_enable(fb_data->display_regulator);
379 if (IS_ERR((void *)ret)) {
380 dev_err(fb_data->dev, "Unable to enable DISPLAY regulator."
381 "err = 0x%x\n", ret);
382 mutex_unlock(&fb_data->power_mutex);
385 ret = regulator_enable(fb_data->vcom_regulator);
386 if (IS_ERR((void *)ret)) {
387 dev_err(fb_data->dev, "Unable to enable VCOM regulator."
388 "err = 0x%x\n", ret);
389 mutex_unlock(&fb_data->power_mutex);
393 fb_data->power_state = POWER_STATE_ON;
394 spdc_panel_pwr_on(fb_data);
396 mutex_unlock(&fb_data->power_mutex);
401 check_waveform(u32 *wv_buf_orig, u32 *wv_buf_cur, u32 wv_buf_size)
404 bool is_mismatch = false;
405 for (i = 0; i < wv_buf_size; i++) {
406 if (wv_buf_orig[i] != wv_buf_cur[i]) {
408 printk(KERN_ERR "Waveform mismatch!\n");
413 printk(KERN_DEBUG "No mismatches!\n");
417 check_waveform(u32 *wv_buf_orig, u32 *wv_buf_cur, u32 wv_buf_size) {}
420 static void get_spdc_version(mxc_spdc_t *fb_data)
422 struct mxc_spdc_version *spdc_ver = &fb_data->spdc_ver;
423 u32 disp_id, tcon_id;
425 disp_id = __raw_readl(fb_data->hwp + SPDC_DISP_VER);
426 tcon_id = __raw_readl(fb_data->hwp + SPDC_TCON_VER);
428 spdc_ver->disp_ver.product_id = disp_id & 0xFFFF;
429 spdc_ver->disp_ver.lut_ver = (disp_id >> 16) & 0xFF;
430 spdc_ver->disp_ver.epd_type = (disp_id >> 24) & 0xFF;
431 spdc_ver->tcon_ver = tcon_id & 0xFF;
433 dev_info(fb_data->dev, "EPD type ID:%x, Tcon ID:%x\n",
434 spdc_ver->disp_ver.product_id, spdc_ver->tcon_ver);
437 static void spdc_set_update_concurrency(mxc_spdc_t *fb_data)
441 concur_mode = fb_data->fresh_param.concur & 0xFF;
442 concur_mode |= (SPDC_LUT_MODE_OFFSET << 8);
444 __raw_writel(concur_mode, fb_data->hwp + SPDC_LUT_PARA_UPDATE);
447 static bool is_preprocess_list_full(mxc_spdc_t *fb_data)
449 /* Check to see if preprocess are full in this list */
450 if (fb_data->upd_preprocess_num >= SPDC_MAX_NUM_PREPROCESS)
456 static void spdc_submit_update(mxc_spdc_t *fb_data)
458 fb_data->updates_active = true;
460 spdc_set_nextbuf_addr(fb_data);
461 spdc_set_update_coord(fb_data);
462 spdc_set_update_dimensions(fb_data);
463 spdc_set_update_temper(fb_data);
464 spdc_trigger_update(fb_data);
467 static int spdc_init_sequence(mxc_spdc_t *fb_data)
469 struct fb_var_screeninfo *screeninfo = &fb_data->spdc_fb_var;
470 struct spdc_buffer_addr *buf_addr = &fb_data->fresh_param.buf_addr;
471 struct imx_spdc_panel_init_set *init_set =
472 fb_data->pdata->spdc_mode->init_set;
477 spdc_powerup(fb_data);
479 /* enable all interrupt */
480 spdc_intr_stat_clear(fb_data, SPDC_INT_STA_CLR);
481 spdc_intr_enable(fb_data, SPDC_IRQ_ALL_MASK);
482 /* set ACC concurrency update mode */
483 if (fb_data->fresh_param.concur)
484 spdc_set_update_concurrency(fb_data);
486 /* program SPDC register and trigger to process buffer*/
487 buf_addr->next_buf_phys_addr = fb_data->phy_next_buf;
488 buf_addr->cur_buf_phys_addr = fb_data->phy_current_buf;
489 buf_addr->pre_buf_phys_addr = fb_data->phy_pre_buf;
490 buf_addr->frm_cnt_buf_phys_addr = fb_data->phy_cnt_buf;
491 buf_addr->lut_buf_phys_addr = fb_data->phy_lut_buf;
493 /* Use unrotated (native) width/height */
494 if ((screeninfo->rotate == FB_ROTATE_CW) ||
495 (screeninfo->rotate == FB_ROTATE_CCW)) {
496 xres = screeninfo->yres;
497 yres = screeninfo->xres;
499 xres = screeninfo->xres;
500 yres = screeninfo->yres;
502 fb_data->fresh_param.update_region.left = 0;
503 fb_data->fresh_param.update_region.top = 0;
504 fb_data->fresh_param.update_region.width = xres;
505 fb_data->fresh_param.update_region.height = yres;
507 /* set panel temperature as environment temperature */
508 fb_data->fresh_param.temper = SPDC_DEFAULT_TEMP;
509 /* set waveform mode */
510 fb_data->fresh_param.wave_mode = SPDC_WAV_MODE_DEFAULT;
512 spdc_set_update_coord(fb_data);
513 spdc_set_update_dimensions(fb_data);
515 spdc_set_update_temper(fb_data);
517 spdc_set_nextbuf_addr(fb_data);
518 spdc_set_curbuf_addr(fb_data);
519 spdc_set_prebuf_addr(fb_data);
520 spdc_set_cntbuf_addr(fb_data);
523 spdc_set_lutbuf_addr(fb_data);
524 ret = wait_for_completion_timeout(&fb_data->lut_down,
525 msecs_to_jiffies(4000));
527 dev_err(fb_data->dev,
528 "Timed out for lut!\n");
532 /* modify lut to fix DC com fading issue,
533 * and fix mode4 close over push
535 __raw_writel(0x00003906, fb_data->hwp + SPDC_LUT_PARA_UPDATE);
536 __raw_writel(0x00003300, fb_data->hwp + SPDC_LUT_PARA_UPDATE);
538 /* init SPDC setting, the setting get from platform data */
539 fb_data->panel_set.yoe_pol = init_set->yoe_pol;
540 fb_data->panel_set.dual_gate = init_set->dual_gate;
541 fb_data->panel_set.ud = init_set->ud;
542 fb_data->panel_set.rl = init_set->rl;
543 fb_data->panel_set.data_filter_n = init_set->data_filter_n;
544 fb_data->panel_set.rgbw_mode_enable = init_set->rgbw_mode_enable;
545 fb_data->panel_set.hburst_len_en = init_set->hburst_len_en;
546 ret = update_panel_init_set(fb_data);
551 static u32 mxc_spdc_partial_refresh_low(mxc_spdc_t *fb_data, void *buffer)
554 void *pattern = buffer;
555 struct partial_refresh_param *fresh_param = &fb_data->fresh_param;
559 fb_data->updates_active = true;
561 fresh_addr = (u8 *)(fb_data->virt_start) +
562 (fresh_param->update_region.top * fresh_param->stride) +
563 ((fresh_param->update_region.left * fb_data->default_bpp) >> 3);
564 fresh_size = (u32)((fresh_param->update_region.width *
565 fresh_param->update_region.height * fb_data->default_bpp) >> 3);
567 if (buffer != NULL) {
568 while (fresh_size > 0) {
569 memcpy((void *)fresh_addr, pattern,
570 fresh_param->update_region.width);
571 fresh_size -= fresh_param->update_region.width;
572 fresh_addr += fresh_param->update_region.top *
574 pattern += fresh_param->update_region.width;
578 /* program SPDC register and trigger to process buffer*/
579 fb_data->fresh_param.buf_addr.next_buf_phys_addr =
580 fb_data->info.fix.smem_start + fb_data->fb_offset;
581 fb_data->fresh_param.wave_mode = fb_data->wv_modes.mode_init;
582 spdc_submit_update(fb_data);
584 ret = wait_for_completion_timeout(&fb_data->update_finish,
585 msecs_to_jiffies(3000));
587 dev_err(fb_data->dev,
588 "display update timeout!\n");
595 static u32 spdc_fb_dev_init(mxc_spdc_t *fb_data)
597 fb_data->auto_mode = AUTO_UPDATE_MODE_REGION_MODE;
598 fb_data->fresh_param.wave_mode = SPDC_WAV_MODE_0;
599 fb_data->operation_mode = SPDC_NO_OPERATION;
600 fb_data->is_deep_fresh = false;
602 /* Init the concurrency update */
603 fb_data->fresh_param.concur = 0;
604 fb_data->upd_preprocess_num = 0;
605 fb_data->submit_upd_sta = 0;
607 fb_data->fresh_param.temper = SPDC_DEFAULT_TEMP;
613 * mxc_spdc_device_is_busy - check spdc device busy status.
614 * Returns 0 if spdc device is idle.
616 static int mxc_spdc_device_is_busy(mxc_spdc_t *fb_data)
619 u32 orig_jiffies = jiffies;
622 status = __raw_readl(fb_data->hwp + SPDC_STATUS);
623 if ((status & SPDC_PANEL_STAUTS_BUSY) &&
624 ((status & 0xF0) == SPDC_TCON_STATUS_IDLE))
627 if (signal_pending(current)) {
628 dev_dbg(fb_data->dev, "SPDC Interrupted\n");
632 if (time_after(jiffies, orig_jiffies +
633 msecs_to_jiffies(3000))) {
634 dev_dbg(fb_data->dev, "SPDC is busy\n");
644 static bool is_free_list_full(mxc_spdc_t *fb_data)
647 struct update_data_list *plist;
649 /* Count buffers in free buffer list */
650 list_for_each_entry(plist, &fb_data->upd_buf_free_list, list)
653 /* Check to see if all buffers are in this list */
654 if (count == fb_data->max_num_updates)
660 static void spdc_draw_mode0(mxc_spdc_t *fb_data)
662 struct mxcfb_update_data update;
663 struct mxcfb_update_marker_data upd_marker_data;
664 struct fb_var_screeninfo *screeninfo = &fb_data->spdc_fb_var;
668 fb_data->fresh_param.buf_addr.next_buf_phys_addr =
671 fb_data->hw_ready = true;
672 fb_data->hw_initializing = false;
674 /* Use unrotated (native) width/height */
675 if ((screeninfo->rotate == FB_ROTATE_CW) ||
676 (screeninfo->rotate == FB_ROTATE_CCW)) {
677 xres = screeninfo->yres;
678 yres = screeninfo->xres;
680 xres = screeninfo->xres;
681 yres = screeninfo->yres;
684 update.update_region.left = 0;
685 update.update_region.width = xres;
686 update.update_region.top = 0;
687 update.update_region.height = yres;
688 update.update_mode = UPDATE_MODE_FULL;
689 update.waveform_mode = fb_data->wv_modes.mode_init;
690 update.update_marker = INIT_UPDATE_MARKER;
691 update.temp = SPDC_DEFAULT_TEMP;
694 upd_marker_data.update_marker = update.update_marker;
696 mxc_spdc_fb_send_update(&update, &fb_data->info);
698 /* Block on initial update */
699 ret = mxc_spdc_fb_wait_update_complete(&upd_marker_data,
702 dev_err(fb_data->dev,
703 "Wait for update complete failed, Err:%d", ret);
707 spdc_fb_fw_handler(const struct firmware *fw, void *context)
709 mxc_spdc_t *fb_data = (mxc_spdc_t *)context;
710 struct clk *spdc_parent;
711 unsigned long rounded_parent_rate, spdc_pix_rate,
712 rounded_pix_clk, target_pix_clk;
717 /* If default FW file load failed, we give up */
718 if (fb_data->fw_default_load)
721 /* Try to load default waveform */
722 fb_data->fw_default_load = true;
724 ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
725 fb_data->fw_str, fb_data->dev, GFP_KERNEL,
726 fb_data, spdc_fb_fw_handler);
728 dev_err(fb_data->dev,
729 "Failed to load waveform image with err %d\n", ret);
734 wv_file = (u8 *)fw->data;
735 memcpy(fb_data->virt_lut_buf, wv_file, fw->size);
737 check_waveform((u32 *)wv_file, (u32 *)fb_data->virt_lut_buf,
739 release_firmware(fw);
741 /* Enable clocks to access SPDC regs */
742 clk_enable(fb_data->spdc_clk_axi);
744 target_pix_clk = fb_data->cur_mode->vmode->pixclock;
745 /* Enable pix clk for SPDC */
746 clk_enable(fb_data->spdc_clk_pix);
747 rounded_pix_clk = clk_round_rate(fb_data->spdc_clk_pix, target_pix_clk);
749 if (((rounded_pix_clk >= target_pix_clk + target_pix_clk/100) ||
750 (rounded_pix_clk <= target_pix_clk - target_pix_clk/100))) {
751 /* Can't get close enough without changing parent clk */
752 spdc_parent = clk_get_parent(fb_data->spdc_clk_pix);
753 rounded_parent_rate =
754 clk_round_rate(spdc_parent, target_pix_clk);
756 spdc_pix_rate = target_pix_clk;
757 while (spdc_pix_rate < rounded_parent_rate)
759 clk_set_rate(spdc_parent, spdc_pix_rate);
762 clk_round_rate(fb_data->spdc_clk_pix, target_pix_clk);
763 if (((rounded_pix_clk >= target_pix_clk + target_pix_clk/100) ||
764 (rounded_pix_clk <= target_pix_clk - target_pix_clk/100)))
765 /* Still can't get a good clock, provide warning */
766 dev_err(fb_data->dev,
767 "Unable to get an accurate SPDC pix clk"
768 "desired = %lu, actual = %lu\n", target_pix_clk,
772 clk_set_rate(fb_data->spdc_clk_pix, rounded_pix_clk);
774 if (!spdc_init_sequence(fb_data))
777 /* display log on picture */
778 spdc_draw_mode0(fb_data);
782 static int spdc_fb_init_hw(struct fb_info *info)
784 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
787 fb_data->fw_default_load = false;
789 * Create fw search string based on ID string in selected videomode.
790 * Format is "imx/spdc_[wave_timing].fw: spdc_pvi.fw, spdc_auo.fw"
792 if (fb_data->cur_mode) {
793 memset(fb_data->fw_str, 0, sizeof(fb_data->fw_str));
794 strcat(fb_data->fw_str, "imx/spdc_");
795 strcat(fb_data->fw_str, fb_data->cur_mode->wave_timing);
796 strcat(fb_data->fw_str, ".fw");
798 strcat(fb_data->fw_str, "imx/spdc_pvi.fw");
800 ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
801 fb_data->fw_str, fb_data->dev, GFP_KERNEL,
802 fb_data, spdc_fb_fw_handler);
804 dev_err(fb_data->dev,
805 "Failed to load waveform image with err %d\n", ret);
812 static int mxc_spdc_partial_refresh(mxc_spdc_t *fb_data, void *buffer)
815 struct partial_refresh_param *fresh_param = &fb_data->fresh_param;
817 if (!fb_data->panel_set.power_ready)
818 spdc_powerup(fb_data);
820 if (!fresh_param->blocking) {
821 if (mxc_spdc_device_is_busy(fb_data)) {
822 dev_err(fb_data->dev, "spdc busy!\n");
826 while (mxc_spdc_device_is_busy(fb_data)) {
827 dev_err(fb_data->dev, "Waiting for spdc idle..\n");
832 ret = mxc_spdc_partial_refresh_low(fb_data, buffer);
837 static int mxc_operaton_update(mxc_spdc_t *fb_data)
840 struct partial_refresh_param *fresh_param = &fb_data->fresh_param;
841 u32 operation_mode = fb_data->operation_mode;
843 if (!fb_data->panel_set.power_ready)
844 spdc_powerup(fb_data);
846 if (operation_mode != SPDC_SW_TCON_RESET) {
847 if (!fresh_param->blocking) {
848 if (mxc_spdc_device_is_busy(fb_data)) {
849 dev_err(fb_data->dev, "spdc busy\n");
853 while (mxc_spdc_device_is_busy(fb_data)) {
854 dev_err(fb_data->dev, "Waiting spdc idle...\n");
859 operation_mode = SPDC_SW_TCON_RESET_SET;
861 /* don't add to queue list */
862 mutex_lock(&fb_data->queue_mutex);
863 __raw_writel(operation_mode, fb_data->hwp + SPDC_OPERATE);
864 mutex_unlock(&fb_data->queue_mutex);
866 if (operation_mode == SPDC_SW_TCON_RESET_SET) {
867 dev_dbg(fb_data->dev, "reinit hw\n");
870 fb_data->hw_ready = false;
871 fb_data->operation_mode = SPDC_NO_OPERATION;
872 ret = spdc_fb_init_hw(&fb_data->info);
873 if (ret && !fb_data->hw_ready)
874 dev_err(fb_data->dev, "Failed to init HW!\n");
880 static int mxc_spdc_refresh_display(mxc_spdc_t *fb_data)
882 struct partial_refresh_param *fresh_param = &fb_data->fresh_param;
883 u32 operation_mode = fb_data->operation_mode;
886 fresh_param->update_region.left = 0;
887 fresh_param->update_region.top = 0;
888 fresh_param->update_region.width = fb_data->spdc_fb_var.xres;
889 fresh_param->update_region.height = fb_data->spdc_fb_var.yres;
890 fresh_param->stride = (fb_data->spdc_fb_var.xres *
891 fb_data->spdc_fb_var.bits_per_pixel) >> 3;
893 if (operation_mode && operation_mode < SPDC_FULL_REFRESH)
894 ret = mxc_operaton_update(fb_data);
896 ret = mxc_spdc_partial_refresh(fb_data, NULL);
901 static void mxc_spdc_find_match_mode(mxc_spdc_t *fb_data)
903 struct imx_spdc_fb_mode *spdc_mode =
904 &fb_data->pdata->spdc_mode[0];
905 const struct mxc_spdc_resolution_map_para *spdc_res_map;
908 u32 default_mode = 0xFF;
910 if (fb_data->panel_set.rgbw_mode_enable)
911 spdc_res_map = &spdc_rgbw_res_map[0];
913 spdc_res_map = &spdc_gray_res_map[0];
915 while (spdc_mode != NULL) {
916 while (spdc_res_map[j].resolution != 0xFFFF) {
917 if (spdc_mode->vmode->xres == spdc_res_map[j].res_x
918 && spdc_mode->vmode->yres == spdc_res_map[j].res_y) {
919 fb_data->panel_set.resolution =
920 spdc_res_map[j].resolution;
927 if (default_mode != 0xFF)
931 spdc_mode = &fb_data->pdata->spdc_mode[i];
934 fb_data->cur_mode = spdc_mode;
937 static int mxc_spdc_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
939 unsigned long start = vma->vm_start;
940 unsigned long size = vma->vm_end - vma->vm_start;
941 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
942 unsigned long page, pos;
944 if (offset + size > info->fix.smem_len)
947 pos = (unsigned long)info->fix.smem_start + offset;
949 /* make buffers bufferable */
950 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
951 vma->vm_flags |= VM_RESERVED | VM_IO;
955 if (io_remap_pfn_range(vma, start, page >> PAGE_SHIFT,
956 PAGE_SIZE, vma->vm_page_prot))
961 if (size > PAGE_SIZE)
970 static inline u_int _chan_to_field(u_int chan, struct fb_bitfield *bf)
973 chan >>= 16 - bf->length;
974 return chan << bf->offset;
977 static int mxc_spdc_fb_setcolreg(u_int regno, u_int red, u_int green,
978 u_int blue, u_int transp, struct fb_info *info)
980 if (regno >= 256) /* no. of hw registers */
983 /* grayscale works only partially under directcolor */
984 if (info->var.grayscale) {
985 /* grayscale = 0.30*R + 0.59*G + 0.11*B */
986 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
989 #define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
990 switch (info->fix.visual) {
991 case FB_VISUAL_TRUECOLOR:
992 case FB_VISUAL_PSEUDOCOLOR:
993 red = CNVT_TOHW(red, info->var.red.length);
994 green = CNVT_TOHW(green, info->var.green.length);
995 blue = CNVT_TOHW(blue, info->var.blue.length);
996 transp = CNVT_TOHW(transp, info->var.transp.length);
998 case FB_VISUAL_DIRECTCOLOR:
999 red = CNVT_TOHW(red, 8); /* expect 8 bit DAC */
1000 green = CNVT_TOHW(green, 8);
1001 blue = CNVT_TOHW(blue, 8);
1002 /* hey, there is bug in transp handling... */
1003 transp = CNVT_TOHW(transp, 8);
1007 /* Truecolor has hardware independent palette */
1008 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1012 ((u32 *) (info->pseudo_palette))[regno] =
1013 (red << info->var.red.offset) |
1014 (green << info->var.green.offset) |
1015 (blue << info->var.blue.offset) |
1016 (transp << info->var.transp.offset);
1022 void mxc_spdc_fb_flush_updates(mxc_spdc_t *fb_data)
1026 /* Grab queue lock to prevent any new updates from being submitted */
1027 mutex_lock(&fb_data->queue_mutex);
1030 * 3 places to check for updates that are active or pending:
1031 * 1) Updates in the pending list
1032 * 2) Update buffers in use (e.g., PxP processing)
1033 * 3) Active updates to panel - We can key off of SPDC
1034 * power state to know if we have active updates.
1036 if (!list_empty(&fb_data->upd_pending_list) ||
1037 !is_free_list_full(fb_data) ||
1038 (fb_data->updates_active == true)) {
1039 /* Initialize event signalling updates are done */
1040 init_completion(&fb_data->updates_done);
1041 fb_data->waiting_for_idle = true;
1043 mutex_unlock(&fb_data->queue_mutex);
1044 /* Wait for any currently active updates to complete */
1045 ret = wait_for_completion_timeout(&fb_data->updates_done,
1046 msecs_to_jiffies(8000));
1048 dev_err(fb_data->dev,
1049 "Flush updates timeout! ret = 0x%x\n", ret);
1051 mutex_lock(&fb_data->queue_mutex);
1052 fb_data->waiting_for_idle = false;
1055 mutex_unlock(&fb_data->queue_mutex);
1058 static int mxc_spdc_fb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
1060 int count, index, r;
1061 u16 *red, *green, *blue, *transp;
1063 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
1066 dev_dbg(fb_data->dev, "setcmap\n");
1068 if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) {
1069 /* Only support an 8-bit, 256 entry lookup */
1070 if (cmap->len != 256)
1073 mxc_spdc_fb_flush_updates(fb_data);
1075 mutex_lock(&fb_data->pxp_mutex);
1077 * Store colormap in pxp_conf structure for later transmit
1078 * to PxP during update process to convert gray pixels.
1080 * Since red=blue=green for pseudocolor visuals, we can
1081 * just use red values.
1083 for (i = 0; i < 256; i++)
1084 fb_data->pxp_conf.proc_data.lut_map[i] =
1085 cmap->red[i] & 0xFF;
1087 fb_data->pxp_conf.proc_data.lut_map_updated = true;
1089 mutex_unlock(&fb_data->pxp_mutex);
1092 green = cmap->green;
1094 transp = cmap->transp;
1095 index = cmap->start;
1097 for (count = 0; count < cmap->len; count++) {
1100 r = mxc_spdc_fb_setcolreg(index++, *red++,
1101 *green++, *blue++, trans, info);
1110 static void adjust_coordinates(u32 xres, u32 yres, u32 rotation,
1111 struct mxcfb_rect *update_region, struct mxcfb_rect *adj_update_region)
1115 /* If adj_update_region == NULL, pass result back in update_region */
1116 /* If adj_update_region == valid, use it to pass back result */
1117 if (adj_update_region)
1120 adj_update_region->top = update_region->top;
1121 adj_update_region->left = update_region->left;
1122 adj_update_region->width = update_region->width;
1123 adj_update_region->height = update_region->height;
1126 adj_update_region->top = update_region->left;
1127 adj_update_region->left = yres -
1128 (update_region->top + update_region->height);
1129 adj_update_region->width = update_region->height;
1130 adj_update_region->height = update_region->width;
1133 adj_update_region->width = update_region->width;
1134 adj_update_region->height = update_region->height;
1135 adj_update_region->top = yres -
1136 (update_region->top + update_region->height);
1137 adj_update_region->left = xres -
1138 (update_region->left + update_region->width);
1141 adj_update_region->left = update_region->top;
1142 adj_update_region->top = xres -
1143 (update_region->left + update_region->width);
1144 adj_update_region->width = update_region->height;
1145 adj_update_region->height = update_region->width;
1151 /* No adjustment needed */
1154 temp = update_region->top;
1155 update_region->top = update_region->left;
1156 update_region->left = yres -
1157 (temp + update_region->height);
1158 temp = update_region->width;
1159 update_region->width = update_region->height;
1160 update_region->height = temp;
1163 update_region->top = yres -
1164 (update_region->top + update_region->height);
1165 update_region->left = xres -
1166 (update_region->left + update_region->width);
1169 temp = update_region->left;
1170 update_region->left = update_region->top;
1171 update_region->top = xres -
1172 (temp + update_region->width);
1173 temp = update_region->width;
1174 update_region->width = update_region->height;
1175 update_region->height = temp;
1180 static int mxc_spdc_fb_set_fix(struct fb_info *info)
1182 struct fb_fix_screeninfo *fix = &info->fix;
1183 struct fb_var_screeninfo *var = &info->var;
1185 fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
1187 fix->type = FB_TYPE_PACKED_PIXELS;
1188 fix->accel = FB_ACCEL_NONE;
1190 fix->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
1192 fix->visual = FB_VISUAL_TRUECOLOR;
1199 static int mxc_spdc_fb_set_par(struct fb_info *info)
1201 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
1202 struct fb_var_screeninfo *screeninfo = &fb_data->info.var;
1203 struct imx_spdc_fb_mode *spdc_modes = fb_data->pdata->spdc_mode;
1204 struct pxp_config_data *pxp_conf = &fb_data->pxp_conf;
1205 struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
1207 __u32 xoffset_old, yoffset_old;
1210 * Can't change the FB parameters until current updates have completed.
1211 * This function returns when all active updates are done.
1213 mxc_spdc_fb_flush_updates(fb_data);
1215 mutex_lock(&fb_data->queue_mutex);
1217 * Set all screeninfo except for xoffset/yoffset
1218 * Subsequent call to pan_display will handle those.
1220 xoffset_old = fb_data->spdc_fb_var.xoffset;
1221 yoffset_old = fb_data->spdc_fb_var.yoffset;
1222 fb_data->spdc_fb_var = *screeninfo;
1223 fb_data->spdc_fb_var.xoffset = xoffset_old;
1224 fb_data->spdc_fb_var.yoffset = yoffset_old;
1225 mutex_unlock(&fb_data->queue_mutex);
1227 mutex_lock(&fb_data->pxp_mutex);
1230 * Update PxP config data (used to process FB regions for updates)
1231 * based on FB info and processing tasks required
1233 /* Initialize non-channel-specific PxP parameters */
1234 proc_data->drect.left = proc_data->srect.left = 0;
1235 proc_data->drect.top = proc_data->srect.top = 0;
1236 proc_data->drect.width = proc_data->srect.width = screeninfo->xres;
1237 proc_data->drect.height = proc_data->srect.height = screeninfo->yres;
1238 proc_data->scaling = 0;
1239 proc_data->hflip = 0;
1240 proc_data->vflip = 0;
1241 proc_data->rotate = screeninfo->rotate;
1242 proc_data->bgcolor = 0;
1243 proc_data->overlay_state = 0;
1244 proc_data->lut_transform = PXP_LUT_NONE;
1247 * configure S0 channel parameters
1248 * Parameters should match FB format/width/height
1250 if (screeninfo->grayscale)
1251 pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_GY04;
1253 switch (screeninfo->bits_per_pixel) {
1255 pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB565;
1258 pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB24;
1261 pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB32;
1264 pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB565;
1268 pxp_conf->s0_param.width = screeninfo->xres_virtual;
1269 pxp_conf->s0_param.height = screeninfo->yres;
1270 pxp_conf->s0_param.color_key = -1;
1271 pxp_conf->s0_param.color_key_enable = false;
1274 * Initialize Output channel parameters
1275 * Output is Y-only greyscale
1276 * Output width/height will vary based on update region size
1278 pxp_conf->out_param.width = screeninfo->xres;
1279 pxp_conf->out_param.height = screeninfo->yres;
1280 pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_GY04;
1282 mutex_unlock(&fb_data->pxp_mutex);
1284 /* active new config, If HW not yet initialized,
1285 * check to see if we are being sent
1286 * an initialization request.
1288 if (!fb_data->hw_ready) {
1289 struct fb_videomode mode;
1290 bool found_match = false;
1293 fb_var_to_videomode(&mode, screeninfo);
1295 /* When comparing requested fb mode,
1296 * we need to use unrotated dimensions
1298 if ((screeninfo->rotate == FB_ROTATE_CW) ||
1299 (screeninfo->rotate == FB_ROTATE_CCW)) {
1300 xres_temp = mode.xres;
1301 mode.xres = mode.yres;
1302 mode.yres = xres_temp;
1305 /* Match videomode against spdc modes */
1306 for (i = 0; i < fb_data->pdata->num_modes; i++) {
1307 if (!fb_mode_is_equal(spdc_modes[i].vmode, &mode))
1309 fb_data->cur_mode = &spdc_modes[i];
1315 dev_err(fb_data->dev,
1316 "Failed to match requested video mode\n");
1320 /* Initialize SPDC settings and init panel */
1322 spdc_fb_init_hw((struct fb_info *)fb_data);
1324 dev_err(fb_data->dev,
1325 "Failed to load panel waveform data\n");
1330 mxc_spdc_fb_set_fix(info);
1336 mxc_spdc_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1338 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
1345 if (var->xres_virtual < var->xoffset + var->xres)
1346 var->xres_virtual = var->xoffset + var->xres;
1347 if (var->yres_virtual < var->yoffset + var->yres)
1348 var->yres_virtual = var->yoffset + var->yres;
1350 if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
1351 (var->bits_per_pixel != 16) && (var->bits_per_pixel != 8) &&
1352 (var->bits_per_pixel != 4))
1353 var->bits_per_pixel = SPDC_DEFAULT_BPP;
1355 switch (var->bits_per_pixel) {
1357 var->red.offset = 0;
1358 var->red.length = var->bits_per_pixel;
1359 var->green = var->red;
1360 var->blue = var->red;
1361 var->transp.offset = 0;
1362 var->transp.length = 0;
1365 if (var->grayscale != 0) {
1366 var->red.length = 8;
1367 var->red.offset = 0;
1368 var->red.msb_right = 0;
1370 var->green = var->red;
1371 var->blue = var->red;
1372 var->transp.length = 0;
1373 var->transp.offset = 0;
1374 var->transp.msb_right = 0;
1376 var->red.length = 3;
1377 var->red.offset = 5;
1378 var->red.msb_right = 0;
1380 var->green.length = 3;
1381 var->green.offset = 2;
1382 var->green.msb_right = 0;
1384 var->blue.length = 2;
1385 var->blue.offset = 0;
1386 var->blue.msb_right = 0;
1388 var->transp.length = 0;
1389 var->transp.offset = 0;
1390 var->transp.msb_right = 0;
1394 var->red.length = 5;
1395 var->red.offset = 11;
1396 var->red.msb_right = 0;
1398 var->green.length = 6;
1399 var->green.offset = 5;
1400 var->green.msb_right = 0;
1402 var->blue.length = 5;
1403 var->blue.offset = 0;
1404 var->blue.msb_right = 0;
1406 var->transp.length = 0;
1407 var->transp.offset = 0;
1408 var->transp.msb_right = 0;
1411 var->red.length = 8;
1412 var->red.offset = 16;
1413 var->red.msb_right = 0;
1415 var->green.length = 8;
1416 var->green.offset = 8;
1417 var->green.msb_right = 0;
1419 var->blue.length = 8;
1420 var->blue.offset = 0;
1421 var->blue.msb_right = 0;
1423 var->transp.length = 0;
1424 var->transp.offset = 0;
1425 var->transp.msb_right = 0;
1428 var->red.length = 8;
1429 var->red.offset = 16;
1430 var->red.msb_right = 0;
1432 var->green.length = 8;
1433 var->green.offset = 8;
1434 var->green.msb_right = 0;
1436 var->blue.length = 8;
1437 var->blue.offset = 0;
1438 var->blue.msb_right = 0;
1440 var->transp.length = 8;
1441 var->transp.offset = 24;
1442 var->transp.msb_right = 0;
1446 switch (var->rotate) {
1449 var->xres = fb_data->native_width;
1450 var->yres = fb_data->native_height;
1454 var->xres = fb_data->native_height;
1455 var->yres = fb_data->native_width;
1458 /* Invalid rotation value */
1460 dev_dbg(fb_data->dev, "Invalid rotation request\n");
1464 var->xres_virtual = ALIGN(var->xres, 32);
1465 var->yres_virtual = ALIGN(var->yres, 128) * fb_data->num_screens;
1473 void mxc_spdc_fb_set_waveform_modes(struct mxcfb_waveform_modes *modes,
1474 struct fb_info *info)
1476 mxc_spdc_t *fb_data = info ?
1477 (mxc_spdc_t *)info:g_fb_data;
1479 mutex_lock(&fb_data->queue_mutex);
1481 memcpy(&fb_data->wv_modes, modes, sizeof(struct mxcfb_waveform_modes));
1483 mutex_unlock(&fb_data->queue_mutex);
1485 EXPORT_SYMBOL(mxc_spdc_fb_set_waveform_modes);
1487 /* To stick with non-fractional degrees for the sake
1488 * of API consistency with EPDC.
1490 int mxc_spdc_fb_set_temperature(int temperature, struct fb_info *info)
1492 mxc_spdc_t *fb_data = info ?
1493 (mxc_spdc_t *)info:g_fb_data;
1494 s8 temper = (s8)(temperature & 0xFF) << 1;
1496 mutex_lock(&fb_data->queue_mutex);
1498 if (temper > -110 && temper < 200)
1499 __raw_writel(temper, fb_data->hwp + SPDC_TEMP_INFO);
1501 __raw_writel(SPDC_DEFAULT_TEMP, fb_data->hwp + SPDC_TEMP_INFO);
1503 mutex_unlock(&fb_data->queue_mutex);
1507 EXPORT_SYMBOL(mxc_spdc_fb_set_temperature);
1510 int mxc_spdc_fb_set_auto_update(u32 auto_mode, struct fb_info *info)
1512 mxc_spdc_t *fb_data = info ?
1513 (mxc_spdc_t *)info:g_fb_data;
1515 dev_dbg(fb_data->dev, "Setting auto update mode to %d\n", auto_mode);
1517 if ((auto_mode == AUTO_UPDATE_MODE_AUTOMATIC_MODE)
1518 || (auto_mode == AUTO_UPDATE_MODE_REGION_MODE))
1519 fb_data->auto_mode = auto_mode;
1521 dev_err(fb_data->dev, "Invalid auto update mode parameter.\n");
1527 EXPORT_SYMBOL(mxc_spdc_fb_set_auto_update);
1530 int mxc_spdc_fb_set_upd_scheme(u32 upd_scheme, struct fb_info *info)
1532 mxc_spdc_t *fb_data = info ?
1533 (mxc_spdc_t *)info:g_fb_data;
1535 dev_dbg(fb_data->dev, "Setting optimization level to %d\n", upd_scheme);
1538 * Can't change the scheme until current updates have completed.
1539 * This function returns when all active updates are done.
1541 mxc_spdc_fb_flush_updates(fb_data);
1543 if ((upd_scheme == UPDATE_SCHEME_SNAPSHOT)
1544 || (upd_scheme == UPDATE_SCHEME_QUEUE)
1545 || (upd_scheme == UPDATE_SCHEME_QUEUE_AND_MERGE))
1546 fb_data->upd_scheme = upd_scheme;
1548 dev_err(fb_data->dev, "Invalid update scheme specified.\n");
1554 EXPORT_SYMBOL(mxc_spdc_fb_set_upd_scheme);
1556 /* Callback function triggered after PxP receives an EOF interrupt */
1557 static void pxp_dma_done(void *arg)
1559 struct pxp_tx_desc *tx_desc = to_tx_desc(arg);
1560 struct dma_chan *chan = tx_desc->txd.chan;
1561 struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1562 mxc_spdc_t *fb_data = pxp_chan->client;
1564 /* This call will signal wait_for_completion_timeout()
1565 * in send_buffer_to_pxp
1567 complete(&fb_data->pxp_tx_cmpl);
1570 static bool chan_filter(struct dma_chan *chan, void *arg)
1572 if (imx_dma_is_pxp(chan))
1578 /* Function to request PXP DMA channel */
1579 static int pxp_chan_init(mxc_spdc_t *fb_data)
1581 dma_cap_mask_t mask;
1582 struct dma_chan *chan;
1585 * Request a free channel
1588 dma_cap_set(DMA_SLAVE, mask);
1589 dma_cap_set(DMA_PRIVATE, mask);
1590 chan = dma_request_channel(mask, chan_filter, NULL);
1592 dev_err(fb_data->dev, "Unsuccessfully received channel!!!!\n");
1596 fb_data->pxp_chan = to_pxp_channel(chan);
1597 fb_data->pxp_chan->client = fb_data;
1599 init_completion(&fb_data->pxp_tx_cmpl);
1605 * Function to call PxP DMA driver and send our latest FB update region
1606 * through the PxP and out to an intermediate buffer.
1607 * Note: This is a blocking call, so upon return the PxP tx should be complete.
1609 static int pxp_process_update(mxc_spdc_t *fb_data,
1610 u32 src_width, u32 src_height,
1611 struct mxcfb_rect *update_region)
1613 dma_cookie_t cookie;
1614 struct scatterlist *sg = fb_data->sg;
1615 struct dma_chan *dma_chan;
1616 struct pxp_tx_desc *desc;
1617 struct dma_async_tx_descriptor *txd;
1618 struct pxp_config_data *pxp_conf = &fb_data->pxp_conf;
1619 struct pxp_proc_data *proc_data = &fb_data->pxp_conf.proc_data;
1623 /* First, check to see that we have acquired a PxP Channel object */
1624 if (fb_data->pxp_chan == NULL) {
1626 * PxP Channel has not yet been created and initialized,
1627 * so let's go ahead and try
1629 ret = pxp_chan_init(fb_data);
1632 * PxP channel init failed, and we can't use the
1633 * PxP until the PxP DMA driver has loaded, so we abort
1635 dev_err(fb_data->dev, "PxP chan init failed\n");
1641 * Init completion, so that we
1642 * can be properly informed of the completion
1643 * of the PxP task when it is done.
1645 init_completion(&fb_data->pxp_tx_cmpl);
1647 dma_chan = &fb_data->pxp_chan->dma_chan;
1649 txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg, 2,
1651 DMA_PREP_INTERRUPT);
1653 dev_err(fb_data->info.device,
1654 "Error preparing a DMA transaction descriptor.\n");
1658 txd->callback_param = txd;
1659 txd->callback = pxp_dma_done;
1662 * Configure PxP for processing of new update region
1663 * The rest of our config params were set up in
1664 * probe() and should not need to be changed.
1666 pxp_conf->s0_param.width = src_width;
1667 pxp_conf->s0_param.height = src_height;
1668 proc_data->srect.top = update_region->top;
1669 proc_data->srect.left = update_region->left;
1670 proc_data->srect.width = update_region->width;
1671 proc_data->srect.height = update_region->height;
1674 * Because only YUV/YCbCr image can be scaled, configure
1675 * drect equivalent to srect, as such do not perform scaling.
1677 proc_data->drect.top = 0;
1678 proc_data->drect.left = 0;
1679 proc_data->drect.width = proc_data->srect.width;
1680 proc_data->drect.height = proc_data->srect.height;
1682 /* PXP expects rotation in terms of degrees */
1683 proc_data->rotate = fb_data->spdc_fb_var.rotate * 90;
1684 if (proc_data->rotate > 270)
1685 proc_data->rotate = 0;
1687 pxp_conf->out_param.width = update_region->width;
1688 pxp_conf->out_param.height = update_region->height;
1690 if ((proc_data->rotate == 90) || (proc_data->rotate == 270))
1691 pxp_conf->out_param.stride = update_region->height;
1693 pxp_conf->out_param.stride = update_region->width;
1695 desc = to_tx_desc(txd);
1697 for (i = 0; i < length; i++) {
1698 if (i == 0) {/* S0 */
1699 memcpy(&desc->proc_data, proc_data,
1700 sizeof(struct pxp_proc_data));
1701 pxp_conf->s0_param.paddr = sg_dma_address(&sg[0]);
1702 memcpy(&desc->layer_param.s0_param, &pxp_conf->s0_param,
1703 sizeof(struct pxp_layer_param));
1704 } else if (i == 1) {
1705 pxp_conf->out_param.paddr = sg_dma_address(&sg[1]);
1706 memcpy(&desc->layer_param.out_param,
1707 &pxp_conf->out_param,
1708 sizeof(struct pxp_layer_param));
1715 /* Submitting our TX starts the PxP processing task */
1716 cookie = txd->tx_submit(txd);
1718 dev_err(fb_data->info.device, "Error sending FB through PxP\n");
1725 dma_async_issue_pending(dma_chan);
1730 static int pxp_complete_update(mxc_spdc_t *fb_data, u32 *hist_stat)
1734 * Wait for completion event, which will be set
1735 * through our TX callback function.
1737 ret = wait_for_completion_timeout(&fb_data->pxp_tx_cmpl, HZ / 10);
1739 dev_info(fb_data->info.device,
1740 "PxP operation failed due to %s\n",
1741 ret < 0 ? "user interrupt" : "timeout");
1742 dma_release_channel(&fb_data->pxp_chan->dma_chan);
1743 fb_data->pxp_chan = NULL;
1744 return ret ? : -ETIMEDOUT;
1747 if ((fb_data->pxp_conf.proc_data.lut_transform & EPDC_FLAG_USE_CMAP) &&
1748 fb_data->pxp_conf.proc_data.lut_map_updated)
1749 fb_data->pxp_conf.proc_data.lut_map_updated = false;
1751 *hist_stat = to_tx_desc(fb_data->txd)->hist_status;
1752 dma_release_channel(&fb_data->pxp_chan->dma_chan);
1753 fb_data->pxp_chan = NULL;
1755 dev_dbg(fb_data->dev, "TX completed\n");
1760 static void copy_to_next_buffer(mxc_spdc_t *fb_data,
1761 struct update_data_list *upd_data_list)
1763 struct mxcfb_update_data *upd_data =
1764 &upd_data_list->update_desc->upd_data;
1765 unsigned char *temp_buf_ptr = fb_data->virt_addr_copybuf;
1766 unsigned char *dst_ptr = upd_data_list->virt_addr;
1767 struct mxcfb_rect adj_update_region;
1768 int dst_stride, left_offs, line_width;
1771 switch (fb_data->spdc_fb_var.rotate) {
1773 adj_update_region.top = upd_data->update_region.top;
1774 adj_update_region.left = upd_data->update_region.left;
1775 adj_update_region.width = upd_data->update_region.width;
1776 adj_update_region.height = upd_data->update_region.height;
1777 dst_stride = fb_data->spdc_fb_var.xres_virtual / 2;
1780 adj_update_region.top = upd_data->update_region.left;
1781 adj_update_region.left = fb_data->spdc_fb_var.yres -
1782 (upd_data->update_region.top +
1783 upd_data->update_region.height);
1784 adj_update_region.width = upd_data->update_region.height;
1785 adj_update_region.height = upd_data->update_region.width;
1786 dst_stride = fb_data->spdc_fb_var.yres / 2;
1789 adj_update_region.width = upd_data->update_region.width;
1790 adj_update_region.height = upd_data->update_region.height;
1791 adj_update_region.top = fb_data->spdc_fb_var.yres -
1792 (upd_data->update_region.top + upd_data->update_region.height);
1793 adj_update_region.left = fb_data->spdc_fb_var.xres -
1794 (upd_data->update_region.left +
1795 upd_data->update_region.width);
1796 dst_stride = fb_data->spdc_fb_var.xres_virtual / 2;
1799 adj_update_region.left = upd_data->update_region.top;
1800 adj_update_region.top = fb_data->spdc_fb_var.xres -
1801 (upd_data->update_region.left +
1802 upd_data->update_region.width);
1803 adj_update_region.width = upd_data->update_region.height;
1804 adj_update_region.height = upd_data->update_region.width;
1805 dst_stride = fb_data->spdc_fb_var.yres / 2;
1809 /* pxp output Y4 data.
1810 * Copy the raw data to related region in next buffer.
1812 left_offs = adj_update_region.left / 2;
1813 line_width = adj_update_region.width / 2;
1815 dst_ptr += (adj_update_region.top * dst_stride + left_offs);
1816 for (i = 0; i < adj_update_region.height; i++) {
1817 /* Copy the full line */
1818 memcpy(dst_ptr, temp_buf_ptr, line_width);
1820 dst_ptr += dst_stride;
1821 temp_buf_ptr += line_width;
1825 static int spdc_process_update(struct update_data_list *upd_data_list,
1826 mxc_spdc_t *fb_data)
1828 /* Region of src buffer for update */
1829 struct mxcfb_rect *src_upd_region;
1830 struct mxcfb_rect pxp_upd_region;
1831 struct update_desc_list *upd_desc_list = upd_data_list->update_desc;
1832 u32 src_width, src_height;
1833 u32 offset_from_4, bytes_per_pixel;
1834 u32 post_rotation_xcoord, post_rotation_ycoord, width_pxp_blocks;
1835 u32 pxp_input_offs, pxp_output_offs, pxp_output_shift;
1836 bool input_unaligned = false;
1838 bool use_temp_buf = false;
1842 * Are we using FB or an alternate (overlay)
1843 * buffer for source of update?
1845 if (upd_desc_list->upd_data.flags & EPDC_FLAG_USE_ALT_BUFFER) {
1846 src_width = upd_desc_list->upd_data.alt_buffer_data.width;
1847 src_height = upd_desc_list->upd_data.alt_buffer_data.height;
1849 &upd_desc_list->upd_data.alt_buffer_data.alt_update_region;
1851 src_width = fb_data->spdc_fb_var.xres_virtual;
1852 src_height = fb_data->spdc_fb_var.yres;
1853 src_upd_region = &upd_desc_list->upd_data.update_region;
1856 if (!(src_upd_region->width == fb_data->spdc_fb_var.xres_virtual &&
1857 fb_data->spdc_fb_var.rotate == FB_ROTATE_UR))
1858 use_temp_buf = true;
1860 bytes_per_pixel = fb_data->spdc_fb_var.bits_per_pixel / 8;
1862 /* Grab pxp_mutex here so that we protect access
1863 * to copybuf in addition to the PxP structures */
1864 mutex_lock(&fb_data->pxp_mutex);
1866 offset_from_4 = src_upd_region->left & 0x3;
1867 input_unaligned = ((offset_from_4 * bytes_per_pixel % 4) != 0) ?
1870 if (input_unaligned) {
1871 /* Leave a gap between PxP input addr
1872 * and update region pixels
1875 (src_upd_region->top * src_width + src_upd_region->left)
1876 * bytes_per_pixel & 0xFFFFFFFC;
1877 /* Update region left changes to reflect
1878 * relative position to input ptr
1880 pxp_upd_region.left = (offset_from_4 * bytes_per_pixel % 4)
1884 (src_upd_region->top * src_width + src_upd_region->left)
1886 pxp_upd_region.left = 0;
1888 pxp_upd_region.top = 0;
1890 /* Update region dimensions to meet 8x8 pixel requirement */
1891 if (fb_data->spdc_fb_var.rotate == 0) {
1892 pxp_upd_region.width = ALIGN(src_upd_region->width, 8);
1893 pxp_upd_region.height = ALIGN(src_upd_region->height, 8);
1895 pxp_upd_region.width =
1896 ALIGN(src_upd_region->width + pxp_upd_region.left, 8);
1897 pxp_upd_region.height = ALIGN(src_upd_region->height, 8);
1900 switch (fb_data->spdc_fb_var.rotate) {
1903 post_rotation_xcoord = pxp_upd_region.left;
1904 post_rotation_ycoord = pxp_upd_region.top;
1905 width_pxp_blocks = pxp_upd_region.width;
1908 width_pxp_blocks = pxp_upd_region.height;
1909 post_rotation_xcoord = width_pxp_blocks -
1910 src_upd_region->height;
1911 post_rotation_ycoord = pxp_upd_region.left;
1914 width_pxp_blocks = pxp_upd_region.width;
1915 post_rotation_xcoord = width_pxp_blocks -
1916 src_upd_region->width - pxp_upd_region.left;
1917 post_rotation_ycoord = pxp_upd_region.height -
1918 src_upd_region->height - pxp_upd_region.top;
1921 width_pxp_blocks = pxp_upd_region.height;
1922 post_rotation_xcoord = pxp_upd_region.top;
1923 post_rotation_ycoord = pxp_upd_region.width -
1924 src_upd_region->width - pxp_upd_region.left;
1928 /* Update region start coord to force PxP to
1929 * process full 8x8 regions
1931 pxp_upd_region.top &= ~0x7;
1932 pxp_upd_region.left &= ~0x7;
1934 pxp_output_shift = ALIGN(post_rotation_xcoord, 8)
1935 - post_rotation_xcoord;
1936 pxp_output_offs = post_rotation_ycoord * width_pxp_blocks
1938 upd_desc_list->spdc_offs = ALIGN(pxp_output_offs, 8);
1940 /* Source address either comes from alternate buffer
1941 provided in update data, or from the framebuffer. */
1942 if (upd_desc_list->upd_data.flags & EPDC_FLAG_USE_ALT_BUFFER)
1943 sg_dma_address(&fb_data->sg[0]) =
1944 upd_desc_list->upd_data.alt_buffer_data.phys_addr
1947 sg_dma_address(&fb_data->sg[0]) =
1948 fb_data->info.fix.smem_start + fb_data->fb_offset
1950 sg_set_page(&fb_data->sg[0],
1951 virt_to_page(fb_data->info.screen_base),
1952 fb_data->info.fix.smem_len,
1953 offset_in_page(fb_data->info.screen_base));
1956 /* Update sg[1] to point to output of PxP proc task */
1957 if (!use_temp_buf) {
1958 sg_dma_address(&fb_data->sg[1]) = upd_data_list->phys_addr;
1959 sg_set_page(&fb_data->sg[1],
1960 virt_to_page(upd_data_list->virt_addr),
1961 fb_data->max_pix_size,
1962 offset_in_page(upd_data_list->virt_addr));
1964 sg_dma_address(&fb_data->sg[1]) = fb_data->phys_addr_copybuf;
1965 sg_set_page(&fb_data->sg[1],
1966 virt_to_page(fb_data->virt_addr_copybuf),
1967 fb_data->max_pix_size,
1968 offset_in_page(fb_data->virt_addr_copybuf));
1972 * Set PxP LUT transform type based on update flags.
1974 fb_data->pxp_conf.proc_data.lut_transform = 0;
1975 if (upd_desc_list->upd_data.flags & EPDC_FLAG_ENABLE_INVERSION)
1976 fb_data->pxp_conf.proc_data.lut_transform |= PXP_LUT_INVERT;
1977 if (upd_desc_list->upd_data.flags & EPDC_FLAG_FORCE_MONOCHROME)
1978 fb_data->pxp_conf.proc_data.lut_transform |=
1979 PXP_LUT_BLACK_WHITE;
1980 if (upd_desc_list->upd_data.flags & EPDC_FLAG_USE_CMAP)
1981 fb_data->pxp_conf.proc_data.lut_transform |=
1985 * Toggle inversion processing if 8-bit
1986 * inverted is the current pixel format.
1988 if (fb_data->spdc_fb_var.grayscale == GRAYSCALE_4BIT_INVERTED)
1989 fb_data->pxp_conf.proc_data.lut_transform ^= PXP_LUT_INVERT;
1991 /* This is a blocking call, so upon return PxP tx should be done */
1992 ret = pxp_process_update(fb_data, src_width, src_height,
1995 dev_err(fb_data->dev, "Unable to submit PxP update task.\n");
1996 mutex_unlock(&fb_data->pxp_mutex);
2000 /* If needed, enable SPDC HW while ePxP is processing */
2001 if ((fb_data->power_state == POWER_STATE_OFF)
2002 || fb_data->powering_down) {
2003 spdc_powerup(fb_data);
2006 /* This is a blocking call, so upon return PxP tx should be done */
2007 ret = pxp_complete_update(fb_data, &hist_stat);
2009 dev_err(fb_data->dev, "Unable to complete PxP update task.\n");
2010 mutex_unlock(&fb_data->pxp_mutex);
2015 copy_to_next_buffer(fb_data, upd_data_list);
2017 mutex_unlock(&fb_data->pxp_mutex);
2019 /* Update waveform mode from PxP histogram results */
2020 if (upd_desc_list->upd_data.waveform_mode == WAVEFORM_MODE_AUTO) {
2021 if (hist_stat & 0x1)
2022 upd_desc_list->upd_data.waveform_mode =
2023 fb_data->wv_modes.mode_du;
2024 else if (hist_stat & 0x2)
2025 upd_desc_list->upd_data.waveform_mode =
2026 fb_data->wv_modes.mode_gc4;
2027 else if (hist_stat & 0x4)
2028 upd_desc_list->upd_data.waveform_mode =
2029 fb_data->wv_modes.mode_gc8;
2030 else if (hist_stat & 0x8)
2031 upd_desc_list->upd_data.waveform_mode =
2032 fb_data->wv_modes.mode_gc16;
2034 upd_desc_list->upd_data.waveform_mode =
2035 fb_data->wv_modes.mode_gc32;
2037 dev_dbg(fb_data->dev, "hist_stat = 0x%x, new waveform = 0x%x\n",
2038 hist_stat, upd_desc_list->upd_data.waveform_mode);
2044 static bool spdc_submit_concur(mxc_spdc_t *fb_data,
2045 struct update_desc_list *update_to_concur)
2047 struct mxcfb_update_data *a, *b;
2048 struct mxcfb_rect *arect, *brect;
2049 struct update_data_list *next_upd;
2052 a = &update_to_concur->upd_data;
2053 arect = &update_to_concur->upd_data.update_region;
2055 list_for_each_entry(next_upd,
2056 &fb_data->upd_buf_preprocess_list, list) {
2057 b = &next_upd->update_desc->upd_data;
2058 brect = &next_upd->update_desc->upd_data.update_region;
2060 /* Updates with different waveform
2061 * must be executed sequentially.
2063 if (a->waveform_mode != b->waveform_mode)
2067 * Concurrency update must has no overlay
2069 if (!(arect->left > (brect->left + brect->width) ||
2070 brect->left > (arect->left + arect->width) ||
2071 arect->top > (brect->top + brect->height) ||
2072 brect->top > (arect->top + arect->height)))
2078 if (i != fb_data->upd_preprocess_num)
2084 static int spdc_submit_merge(struct update_desc_list *upd_desc_list,
2085 struct update_desc_list *update_to_merge)
2087 struct mxcfb_update_data *a, *b;
2088 struct mxcfb_rect *arect, *brect;
2089 struct mxcfb_rect combine;
2090 bool use_flags = false;
2092 a = &upd_desc_list->upd_data;
2093 b = &update_to_merge->upd_data;
2094 arect = &upd_desc_list->upd_data.update_region;
2095 brect = &update_to_merge->upd_data.update_region;
2098 * Updates with different flags must be executed sequentially.
2099 * Halt the merge process to ensure this.
2101 if (a->flags != b->flags) {
2103 * Special exception: if update regions are identical,
2104 * we may be able to merge them.
2106 if ((arect->left != brect->left) ||
2107 (arect->top != brect->top) ||
2108 (arect->width != brect->width) ||
2109 (arect->height != brect->height))
2115 if (a->waveform_mode != b->waveform_mode)
2116 a->waveform_mode = WAVEFORM_MODE_AUTO;
2118 if (arect->left > (brect->left + brect->width) ||
2119 brect->left > (arect->left + arect->width) ||
2120 arect->top > (brect->top + brect->height) ||
2121 brect->top > (arect->top + arect->height))
2124 combine.left = arect->left < brect->left ? arect->left : brect->left;
2125 combine.top = arect->top < brect->top ? arect->top : brect->top;
2126 combine.width = (arect->left + arect->width) >
2127 (brect->left + brect->width) ?
2128 (arect->left + arect->width - combine.left) :
2129 (brect->left + brect->width - combine.left);
2130 combine.height = (arect->top + arect->height) >
2131 (brect->top + brect->height) ?
2132 (arect->top + arect->height - combine.top) :
2133 (brect->top + brect->height - combine.top);
2137 /* Use flags of the later update */
2139 a->flags = b->flags;
2142 list_splice_tail(&update_to_merge->upd_marker_list,
2143 &upd_desc_list->upd_marker_list);
2149 static void spdc_submit_work_func(struct work_struct *work)
2151 struct update_desc_list *next_desc, *temp_desc;
2152 mxc_spdc_t *fb_data =
2153 container_of(work, mxc_spdc_t, spdc_submit_work);
2154 struct update_data_list *upd_data_list = NULL;
2155 struct mxcfb_rect adj_update_region, *upd_region;
2156 struct update_marker_data *current_marker;
2157 bool end_merge = false;
2161 /* Protect access to buffer queues and to update HW */
2162 mutex_lock(&fb_data->queue_mutex);
2164 /* get a buffer from free list */
2165 if (list_empty(&fb_data->upd_buf_free_list)) {
2166 mutex_unlock(&fb_data->queue_mutex);
2170 if (fb_data->fresh_param.concur == SPDC_LUT_ACC_MODE) {
2171 list_for_each_entry_safe(next_desc, temp_desc,
2172 &fb_data->upd_pending_list, list) {
2175 list_entry((&next_desc->upd_marker_list)->next,
2176 struct update_marker_data, upd_list);
2178 if (current_marker->update_marker) {
2179 fb_data->submit_upd_sta = 0;
2183 /* require free buffer list */
2184 if (list_empty(&fb_data->upd_buf_free_list)) {
2185 dev_dbg(fb_data->dev,
2186 "buf free list is empty\n");
2191 list_entry(fb_data->upd_buf_free_list.next,
2192 struct update_data_list, list);
2193 upd_data_list->update_desc = next_desc;
2195 if (!is_preprocess_list_full(fb_data)) {
2196 if (fb_data->cur_update == NULL &&
2197 !fb_data->upd_preprocess_num)
2198 list_del_init(&next_desc->list);
2199 else if (spdc_submit_concur(fb_data,
2201 list_del_init(&next_desc->list);
2202 list_add_tail(&upd_data_list->list,
2203 &fb_data->upd_buf_preprocess_list);
2204 fb_data->upd_preprocess_num++;
2205 fb_data->submit_upd_sta =
2212 /* submit to pxp process */
2213 list_del_init(&upd_data_list->list);
2217 upd_data_list = NULL;
2218 if (fb_data->submit_upd_sta == SPDC_CONCUR_UPD)
2219 fb_data->submit_upd_sta |= SPDC_QUEUE_UPD;
2221 fb_data->submit_upd_sta = SPDC_QUEUE_UPD;
2224 list_for_each_entry_safe(next_desc, temp_desc,
2225 &fb_data->upd_pending_list, list) {
2227 if (!upd_data_list) {
2229 if (list_empty(&fb_data->upd_buf_free_list)) {
2230 dev_dbg(fb_data->dev,
2231 "buf_free_list is empty\n");
2235 list_entry(fb_data->upd_buf_free_list.next,
2236 struct update_data_list, list);
2237 list_del_init(&upd_data_list->list);
2238 upd_data_list->update_desc = next_desc;
2239 list_del_init(&next_desc->list);
2241 if (fb_data->upd_scheme == UPDATE_SCHEME_QUEUE)
2244 switch (spdc_submit_merge(upd_data_list->update_desc,
2247 dev_dbg(fb_data->dev,
2248 "Update merged [queue]\n");
2249 list_del_init(&next_desc->list);
2253 dev_dbg(fb_data->dev,
2254 "Update not merged [queue]\n");
2257 dev_dbg(fb_data->dev,
2258 "Merge blocked [collision]\n");
2268 /* Is update list empty? */
2269 if (!upd_data_list) {
2270 mutex_unlock(&fb_data->queue_mutex);
2276 * If no processing required, skip update processing
2277 * No processing means:
2279 * - FB pixel format = 4-bit grayscale
2280 * - No look-up transformations (inversion, posterization, etc.)
2282 is_transform = upd_data_list->update_desc->upd_data.flags &
2283 (EPDC_FLAG_ENABLE_INVERSION |
2284 EPDC_FLAG_FORCE_MONOCHROME | EPDC_FLAG_USE_CMAP) ?
2286 if ((fb_data->spdc_fb_var.rotate == FB_ROTATE_UR) &&
2287 (fb_data->spdc_fb_var.grayscale == GRAYSCALE_4BIT) &&
2290 /* If needed, enable SPDC HW while ePxP is processing */
2291 if ((fb_data->power_state == POWER_STATE_OFF)
2292 || fb_data->powering_down)
2293 spdc_powerup(fb_data);
2296 * Set update buffer pointer to the start of
2297 * the update region in the frame buffer.
2300 &upd_data_list->update_desc->upd_data.update_region;
2301 update_addr = fb_data->info.fix.smem_start +
2302 ((upd_region->top * fb_data->info.var.xres_virtual) +
2303 upd_region->left) * fb_data->info.var.bits_per_pixel/8;
2306 /* Select from PxP output buffers */
2307 upd_data_list->phys_addr =
2308 fb_data->phys_addr_updbuf[fb_data->upd_buffer_num];
2309 upd_data_list->virt_addr =
2310 fb_data->virt_addr_updbuf[fb_data->upd_buffer_num];
2311 fb_data->upd_buffer_num++;
2312 if (fb_data->upd_buffer_num > fb_data->max_num_buffers-1)
2313 fb_data->upd_buffer_num = 0;
2314 dev_dbg(fb_data->dev,
2315 "pxp out addr:0x%x\n", upd_data_list->phys_addr);
2317 /* Release buffer queues */
2318 mutex_unlock(&fb_data->queue_mutex);
2320 /* Perform PXP processing - SPDC power will also be enabled */
2321 if (spdc_process_update(upd_data_list, fb_data)) {
2323 dev_dbg(fb_data->dev, "PXP processing error.\n");
2324 /* Protect access to buffer queues and to update HW */
2325 mutex_lock(&fb_data->queue_mutex);
2326 list_del_init(&upd_data_list->update_desc->list);
2327 kfree(upd_data_list->update_desc);
2328 upd_data_list->update_desc = NULL;
2330 /* Add to free buffer list */
2331 list_add_tail(&upd_data_list->list,
2332 &fb_data->upd_buf_free_list);
2333 /* Release buffer queues */
2334 mutex_unlock(&fb_data->queue_mutex);
2338 /* Protect access to buffer queues and to update HW */
2339 mutex_lock(&fb_data->queue_mutex);
2341 /* output Y4 format */
2342 update_addr = upd_data_list->phys_addr +
2343 + (upd_data_list->update_desc->spdc_offs / 2);
2346 /* Get rotation-adjusted coordinates */
2347 adjust_coordinates(fb_data->spdc_fb_var.xres,
2348 fb_data->spdc_fb_var.yres, fb_data->spdc_fb_var.rotate,
2349 &upd_data_list->update_desc->upd_data.update_region,
2350 &adj_update_region);
2353 * Is the working buffer idle?
2354 * If the working buffer is busy, we must wait for the resource
2357 if (fb_data->cur_update != NULL &&
2358 fb_data->submit_upd_sta != SPDC_CONCUR_UPD) {
2359 /* Initialize event signalling an update resource is free */
2360 init_completion(&fb_data->update_res_free);
2362 fb_data->waiting_for_wb = true;
2364 /* Leave spinlock while waiting for WB to complete */
2365 mutex_unlock(&fb_data->queue_mutex);
2366 wait_for_completion(&fb_data->update_res_free);
2367 mutex_lock(&fb_data->queue_mutex);
2370 if (fb_data->submit_upd_sta != SPDC_CONCUR_UPD)
2371 fb_data->cur_update = upd_data_list;
2373 /* program SPDC register and trigger to process buffer*/
2374 fb_data->fresh_param.buf_addr.next_buf_phys_addr = update_addr;
2376 fb_data->fresh_param.update_region.left = adj_update_region.left;
2377 fb_data->fresh_param.update_region.top = adj_update_region.top;
2378 fb_data->fresh_param.update_region.width = adj_update_region.width;
2379 fb_data->fresh_param.update_region.height = adj_update_region.height;
2380 fb_data->fresh_param.temper = upd_data_list->update_desc->upd_data.temp;
2381 fb_data->fresh_param.wave_mode =
2382 upd_data_list->update_desc->upd_data.waveform_mode;
2384 spdc_submit_update(fb_data);
2386 /* Release buffer queues */
2387 mutex_unlock(&fb_data->queue_mutex);
2390 int mxc_spdc_fb_send_update(struct mxcfb_update_data *upd_data,
2391 struct fb_info *info)
2393 mxc_spdc_t *fb_data = info ?
2394 (mxc_spdc_t *)info:g_fb_data;
2395 struct update_data_list *upd_data_list = NULL;
2396 struct mxcfb_rect *screen_upd_region; /* Region on screen to update */
2397 struct update_desc_list *upd_desc;
2398 struct update_marker_data *marker_data;
2401 /* Has SPDC HW been initialized? */
2402 if (!fb_data->hw_ready) {
2403 /* Throw message if we are not mid-initialization */
2404 if (!fb_data->hw_initializing)
2405 dev_err(fb_data->dev, "Display HW not properly"
2406 "initialized. Aborting update.\n");
2410 if ((upd_data->waveform_mode > SPDC_WAV_MODE_5) &&
2411 (upd_data->waveform_mode != WAVEFORM_MODE_AUTO)) {
2412 dev_err(fb_data->dev,
2413 "Update waveform mode 0x%x is invalid."
2414 " Aborting update.\n",
2415 upd_data->waveform_mode);
2418 if ((upd_data->update_region.left + upd_data->update_region.width >
2419 fb_data->spdc_fb_var.xres + 1) ||
2420 (upd_data->update_region.top + upd_data->update_region.height >
2421 fb_data->spdc_fb_var.yres + 1)) {
2422 dev_err(fb_data->dev,
2423 "Update region is outside bounds of framebuffer."
2424 "Aborting update.\n");
2427 if (upd_data->flags & EPDC_FLAG_USE_ALT_BUFFER) {
2428 if ((upd_data->update_region.width !=
2429 upd_data->alt_buffer_data.alt_update_region.width) ||
2430 (upd_data->update_region.height !=
2431 upd_data->alt_buffer_data.alt_update_region.height)) {
2432 dev_err(fb_data->dev,
2433 "Alternate update region dimensions must "
2434 "match screen update region dimensions.\n");
2437 /* Validate physical address parameter */
2438 if ((upd_data->alt_buffer_data.phys_addr <
2439 fb_data->info.fix.smem_start) ||
2440 (upd_data->alt_buffer_data.phys_addr >
2441 fb_data->info.fix.smem_start + fb_data->map_size)) {
2442 dev_err(fb_data->dev,
2443 "Invalid physical address for alternate "
2444 "buffer. Aborting update...\n");
2449 mutex_lock(&fb_data->queue_mutex);
2452 * If we are waiting to go into suspend, or the FB is blanked,
2453 * we do not accept new updates
2455 if (fb_data->waiting_for_idle) {
2456 dev_dbg(fb_data->dev, "SPDC not active."
2457 "Update request abort.\n");
2458 mutex_unlock(&fb_data->queue_mutex);
2462 if (fb_data->upd_scheme == UPDATE_SCHEME_SNAPSHOT) {
2464 struct update_data_list *plist;
2466 /* Count buffers in free buffer list */
2467 list_for_each_entry(plist, &fb_data->upd_buf_free_list, list)
2470 /* Use count to determine if we have enough
2471 * free buffers to handle this update request */
2472 if (count + fb_data->max_num_buffers
2473 <= fb_data->max_num_updates) {
2474 dev_err(fb_data->dev,
2475 "No free intermediate buffers available.\n");
2476 mutex_unlock(&fb_data->queue_mutex);
2480 /* Grab first available buffer and delete from the free list */
2482 list_entry(fb_data->upd_buf_free_list.next,
2483 struct update_data_list, list);
2485 list_del_init(&upd_data_list->list);
2489 * Create new update data structure, fill it with new update
2490 * data and add it to the list of pending updates
2492 upd_desc = kzalloc(sizeof(struct update_desc_list), GFP_KERNEL);
2494 dev_err(fb_data->dev,
2495 "Insufficient system memory for update! Aborting.\n");
2496 if (fb_data->upd_scheme == UPDATE_SCHEME_SNAPSHOT) {
2497 list_add(&upd_data_list->list,
2498 &fb_data->upd_buf_free_list);
2500 mutex_unlock(&fb_data->queue_mutex);
2503 /* Initialize per-update marker list */
2504 INIT_LIST_HEAD(&upd_desc->upd_marker_list);
2505 upd_desc->upd_data = *upd_data;
2506 list_add_tail(&upd_desc->list, &fb_data->upd_pending_list);
2508 /* If marker specified, associate it with a completion */
2509 if (upd_data->update_marker != 0) {
2511 /* Allocate new update marker and set it up */
2512 marker_data = kzalloc(sizeof(struct update_marker_data),
2515 dev_err(fb_data->dev, "No memory for marker!\n");
2516 mutex_unlock(&fb_data->queue_mutex);
2519 list_add_tail(&marker_data->upd_list,
2520 &upd_desc->upd_marker_list);
2521 marker_data->update_marker = upd_data->update_marker;
2522 init_completion(&marker_data->update_completion);
2524 /* Add marker to master marker list */
2525 list_add_tail(&marker_data->full_list,
2526 &fb_data->full_marker_list);
2529 if (fb_data->upd_scheme != UPDATE_SCHEME_SNAPSHOT) {
2530 /* Queued update scheme processing */
2532 mutex_unlock(&fb_data->queue_mutex);
2534 /* Signal workqueue to handle new update */
2535 queue_work(fb_data->spdc_submit_workqueue,
2536 &fb_data->spdc_submit_work);
2541 /* Set descriptor for current update, delete from pending list */
2542 upd_data_list->update_desc = upd_desc;
2543 list_del_init(&upd_desc->list);
2545 mutex_unlock(&fb_data->queue_mutex);
2548 * Hold on to original screen update region, which we
2549 * will ultimately use when telling SPDC where to update on panel
2551 screen_upd_region = &upd_desc->upd_data.update_region;
2553 /* Select from PxP output buffers */
2554 upd_data_list->phys_addr =
2555 fb_data->phys_addr_updbuf[fb_data->upd_buffer_num];
2556 upd_data_list->virt_addr =
2557 fb_data->virt_addr_updbuf[fb_data->upd_buffer_num];
2558 fb_data->upd_buffer_num++;
2559 if (fb_data->upd_buffer_num > fb_data->max_num_buffers-1)
2560 fb_data->upd_buffer_num = 0;
2562 ret = spdc_process_update(upd_data_list, fb_data);
2564 mutex_unlock(&fb_data->pxp_mutex);
2568 /* Pass selected waveform mode back to user */
2569 upd_data->waveform_mode = upd_desc->upd_data.waveform_mode;
2571 /* Get rotation-adjusted coordinates */
2572 adjust_coordinates(fb_data->spdc_fb_var.xres,
2573 fb_data->spdc_fb_var.yres, fb_data->spdc_fb_var.rotate,
2574 &upd_desc->upd_data.update_region, NULL);
2576 /* Grab lock for queue manipulation and update submission */
2577 mutex_lock(&fb_data->queue_mutex);
2580 * Is the working buffer idle?
2581 * If either the working buffer is busy, or there are no LUTs available,
2582 * then we return and let the ISR handle the update later
2584 if (fb_data->cur_update != NULL) {
2586 /* Add processed Y buffer to update list */
2587 list_add_tail(&upd_data_list->list, &fb_data->upd_buf_queue);
2589 /* Return and allow the update to be submitted by the ISR. */
2590 mutex_unlock(&fb_data->queue_mutex);
2594 /* Save current update */
2595 fb_data->cur_update = upd_data_list;
2597 /* program SPDC register and trigger to process buffer*/
2598 fb_data->fresh_param.buf_addr.next_buf_phys_addr =
2599 upd_data_list->phys_addr + (upd_data_list->update_desc->spdc_offs / 2);
2601 fb_data->fresh_param.update_region.left = screen_upd_region->left;
2602 fb_data->fresh_param.update_region.top = screen_upd_region->top;
2603 fb_data->fresh_param.update_region.width = screen_upd_region->width;
2604 fb_data->fresh_param.update_region.height = screen_upd_region->height;
2605 fb_data->fresh_param.temper = upd_desc->upd_data.temp;
2606 fb_data->fresh_param.wave_mode = upd_desc->upd_data.waveform_mode;
2607 spdc_submit_update(fb_data);
2609 mutex_unlock(&fb_data->queue_mutex);
2612 EXPORT_SYMBOL(mxc_spdc_fb_send_update);
2615 * return 0 : spdc update is update
2618 mxc_spdc_fb_wait_update_complete(struct mxcfb_update_marker_data *marker_data,
2619 struct fb_info *info)
2621 mxc_spdc_t *fb_data = info ?
2622 (mxc_spdc_t *)info:g_fb_data;
2623 struct update_marker_data *next_marker;
2624 struct update_marker_data *temp;
2625 bool marker_found = false;
2628 /* 0 is an invalid update_marker value */
2629 if (marker_data->update_marker == 0)
2633 * Find completion associated with update_marker requested.
2634 * Note: If update completed already, marker will have been
2635 * cleared, it won't be found, and function will just return.
2638 /* Grab queue lock to protect access to marker list */
2639 mutex_lock(&fb_data->queue_mutex);
2641 list_for_each_entry_safe(next_marker, temp,
2642 &fb_data->full_marker_list, full_list) {
2643 if (next_marker->update_marker == marker_data->update_marker) {
2644 dev_dbg(fb_data->dev, "Waiting for marker %d\n",
2645 marker_data->update_marker);
2646 next_marker->waiting = true;
2647 marker_found = true;
2652 mutex_unlock(&fb_data->queue_mutex);
2655 * If marker not found, it has either been signalled already
2656 * or the update request failed. In either case, just return.
2661 ret = wait_for_completion_timeout(&next_marker->update_completion,
2662 msecs_to_jiffies(8000));
2664 dev_err(fb_data->dev,
2665 "Timed out waiting for update completion\n");
2669 /** since SPDC don't support auto collision detect,
2670 * there alway returns no collision
2672 marker_data->collision_test = false;
2674 /* Free update marker object */
2679 EXPORT_SYMBOL(mxc_spdc_fb_wait_update_complete);
2681 int mxc_spdc_fb_set_pwrdown_delay(u32 pwrdown_delay,
2682 struct fb_info *info)
2684 mxc_spdc_t *fb_data = info ?
2685 (mxc_spdc_t *)info:g_fb_data;
2687 fb_data->pwrdown_delay = pwrdown_delay;
2691 EXPORT_SYMBOL(mxc_spdc_fb_set_pwrdown_delay);
2693 int mxc_spdc_get_pwrdown_delay(struct fb_info *info)
2695 mxc_spdc_t *fb_data = info ?
2696 (mxc_spdc_t *)info:g_fb_data;
2698 return fb_data->pwrdown_delay;
2700 EXPORT_SYMBOL(mxc_spdc_get_pwrdown_delay);
2703 mxc_spdc_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2705 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
2706 void __user *argp = (void __user *)arg;
2709 dev_dbg(fb_data->dev, "cmd = %08X, arg = %08X\n", cmd, (u32)arg);
2712 case MXCFB_SET_WAVEFORM_MODES:
2714 struct mxcfb_waveform_modes modes;
2715 if (!copy_from_user(&modes, argp, sizeof(modes))) {
2716 mxc_spdc_fb_set_waveform_modes(&modes, info);
2721 case MXCFB_SET_TEMPERATURE:
2724 if (!get_user(temperature, (int32_t __user *) arg))
2725 ret = mxc_spdc_fb_set_temperature(temperature,
2729 case MXCFB_SET_AUTO_UPDATE_MODE:
2732 if (!get_user(auto_mode, (__u32 __user *) arg))
2733 ret = mxc_spdc_fb_set_auto_update(auto_mode,
2737 case MXCFB_SET_UPDATE_SCHEME:
2740 if (!get_user(upd_scheme, (__u32 __user *) arg))
2741 ret = mxc_spdc_fb_set_upd_scheme(upd_scheme,
2745 case MXCFB_SEND_UPDATE:
2747 struct mxcfb_update_data upd_data;
2748 if (!copy_from_user(&upd_data, argp,
2749 sizeof(upd_data))) {
2750 ret = mxc_spdc_fb_send_update(&upd_data, info);
2751 if (ret == 0 && copy_to_user(argp, &upd_data,
2760 case MXCFB_WAIT_FOR_UPDATE_COMPLETE:
2762 struct mxcfb_update_marker_data upd_marker_data;
2763 if (!copy_from_user(&upd_marker_data, argp,
2764 sizeof(upd_marker_data))) {
2765 ret = mxc_spdc_fb_wait_update_complete(
2766 &upd_marker_data, info);
2767 if (copy_to_user(argp, &upd_marker_data,
2768 sizeof(upd_marker_data)))
2776 case MXCFB_SET_PWRDOWN_DELAY:
2779 if (!get_user(delay, (__u32 __user *) arg))
2781 mxc_spdc_fb_set_pwrdown_delay(delay, info);
2784 case MXCFB_GET_PWRDOWN_DELAY:
2786 int pwrdown_delay = mxc_spdc_get_pwrdown_delay(info);
2787 if (put_user(pwrdown_delay, (int __user *)arg))
2792 dev_err(fb_data->dev, "IOCTL_CMD: not such command\n");
2799 static void mxc_spdc_fb_update_pages(mxc_spdc_t *fb_data, u16 y1, u16 y2)
2801 struct mxcfb_update_data update;
2803 /* Do partial screen update, Update full horizontal lines */
2804 update.update_region.left = 0;
2805 update.update_region.width = fb_data->spdc_fb_var.xres;
2806 update.update_region.top = y1;
2807 update.update_region.height = y2 - y1;
2808 update.waveform_mode = WAVEFORM_MODE_AUTO;
2809 update.update_mode = UPDATE_MODE_FULL;
2810 update.update_marker = 0;
2811 update.temp = SPDC_DEFAULT_TEMP;
2814 mxc_spdc_fb_send_update(&update, &fb_data->info);
2817 /* this is called back from the deferred io workqueue */
2818 static void mxc_spdc_fb_deferred_io(struct fb_info *info,
2819 struct list_head *pagelist)
2821 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
2823 unsigned long beg, end;
2824 int y1, y2, miny, maxy;
2826 if (fb_data->auto_mode != AUTO_UPDATE_MODE_AUTOMATIC_MODE)
2831 list_for_each_entry(page, pagelist, lru) {
2832 beg = page->index << PAGE_SHIFT;
2833 end = beg + PAGE_SIZE - 1;
2834 y1 = beg / info->fix.line_length;
2835 y2 = end / info->fix.line_length;
2836 if (y2 >= fb_data->spdc_fb_var.yres)
2837 y2 = fb_data->spdc_fb_var.yres - 1;
2844 mxc_spdc_fb_update_pages(fb_data, miny, maxy);
2847 static int mxc_spdc_fb_blank(int blank, struct fb_info *info)
2849 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
2852 dev_dbg(fb_data->dev, "blank = %d\n", blank);
2854 if (fb_data->blank == blank)
2857 fb_data->blank = blank;
2859 case FB_BLANK_POWERDOWN:
2860 mxc_spdc_fb_flush_updates(fb_data);
2861 /* Wait for powerdown */
2862 mutex_lock(&fb_data->power_mutex);
2863 if ((fb_data->power_state == POWER_STATE_ON) &&
2864 (fb_data->pwrdown_delay == FB_POWERDOWN_DISABLE)) {
2866 /* Powerdown disabled, so we disable SPDC manually */
2870 mutex_unlock(&fb_data->power_mutex);
2872 /* If any active updates, wait for them to complete */
2873 while (fb_data->updates_active) {
2874 /* Timeout after 1 sec */
2875 if ((count * sleep_ms) > 1000)
2881 fb_data->powering_down = true;
2882 spdc_powerdown(fb_data);
2883 } else if (fb_data->power_state != POWER_STATE_OFF) {
2884 fb_data->wait_for_powerdown = true;
2885 init_completion(&fb_data->powerdown_compl);
2886 mutex_unlock(&fb_data->power_mutex);
2888 wait_for_completion_timeout(&fb_data->powerdown_compl,
2889 msecs_to_jiffies(5000));
2891 dev_err(fb_data->dev,
2892 "No powerdown received!\n");
2896 mutex_unlock(&fb_data->power_mutex);
2898 case FB_BLANK_VSYNC_SUSPEND:
2899 case FB_BLANK_HSYNC_SUSPEND:
2900 case FB_BLANK_NORMAL:
2901 mxc_spdc_fb_flush_updates(fb_data);
2908 static int mxc_spdc_fb_pan_display(struct fb_var_screeninfo *var,
2909 struct fb_info *info)
2911 mxc_spdc_t *fb_data = info ?
2912 (mxc_spdc_t *)info:g_fb_data;
2915 dev_dbg(info->device, "%s: var->yoffset %d, info->var.yoffset %d\n",
2916 __func__, var->yoffset, info->var.yoffset);
2917 /* check if var is valid; also, xpan is not supported */
2918 if (!var || (var->xoffset != info->var.xoffset) ||
2919 (var->yoffset + var->yres > var->yres_virtual)) {
2920 dev_dbg(info->device, "x panning not supported\n");
2924 if ((fb_data->spdc_fb_var.xoffset == var->xoffset) &&
2925 (fb_data->spdc_fb_var.yoffset == var->yoffset))
2926 return 0; /* No change, do nothing */
2928 y_bottom = var->yoffset;
2930 if (!(var->vmode & FB_VMODE_YWRAP))
2931 y_bottom += var->yres;
2933 if (y_bottom > info->var.yres_virtual)
2936 mutex_lock(&fb_data->queue_mutex);
2938 fb_data->fb_offset = (var->yoffset * var->xres_virtual + var->xoffset)
2939 * (var->bits_per_pixel) / 8;
2941 fb_data->spdc_fb_var.xoffset = var->xoffset;
2942 fb_data->spdc_fb_var.yoffset = var->yoffset;
2944 if (var->vmode & FB_VMODE_YWRAP)
2945 info->var.vmode |= FB_VMODE_YWRAP;
2947 info->var.vmode &= ~FB_VMODE_YWRAP;
2949 mutex_unlock(&fb_data->queue_mutex);
2954 static struct fb_ops mxc_spdc_fb_ops = {
2955 .owner = THIS_MODULE,
2956 .fb_check_var = mxc_spdc_fb_check_var,
2957 .fb_set_par = mxc_spdc_fb_set_par,
2958 .fb_setcmap = mxc_spdc_fb_setcmap,
2959 .fb_setcolreg = mxc_spdc_fb_setcolreg,
2960 .fb_pan_display = mxc_spdc_fb_pan_display,
2961 .fb_ioctl = mxc_spdc_fb_ioctl,
2962 .fb_mmap = mxc_spdc_fb_mmap,
2963 .fb_blank = mxc_spdc_fb_blank,
2964 .fb_fillrect = cfb_fillrect,
2965 .fb_copyarea = cfb_copyarea,
2966 .fb_imageblit = cfb_imageblit,
2969 static struct fb_deferred_io mxc_spdc_fb_defio = {
2971 .deferred_io = mxc_spdc_fb_deferred_io,
2974 static void spdc_done_work_func(struct work_struct *work)
2976 mxc_spdc_t *fb_data =
2977 container_of(work, mxc_spdc_t, spdc_done_work.work);
2978 spdc_powerdown(fb_data);
2981 static irqreturn_t mxc_spdc_irq_handler(int irq, void *dev_id)
2983 mxc_spdc_t *fb_data = (mxc_spdc_t *)dev_id;
2986 irqreturn_t ret = IRQ_NONE;
2988 spin_lock_irqsave(&fb_data->lock, flags);
2990 int_events = spdc_get_intr_stat(fb_data);
2991 dev_dbg(fb_data->dev, "spdc int:%x\n", int_events);
2993 if (int_events & SPDC_IRQ_STA_ERR) {
2995 spdc_intr_stat_clear(fb_data, SPDC_IRQ_STA_ERR);
2996 dev_err(fb_data->dev, "Error IRQ\n");
3001 * If we just completed one-time panel init, bypass
3002 * queue handling, clear interrupt and return
3004 if (fb_data->operation_mode &&
3005 (int_events & SPDC_IRQ_STA_FRAME_UPDATE)) {
3006 mutex_lock(&fb_data->queue_mutex);
3007 fb_data->updates_active = false;
3008 complete(&fb_data->update_finish);
3009 spdc_intr_stat_clear(fb_data, SPDC_IRQ_STA_FRAME_UPDATE);
3011 if ((fb_data->operation_mode == SPDC_DEEP_REFRESH) ||
3012 fb_data->is_deep_fresh)
3013 fb_data->is_deep_fresh = false;
3015 fb_data->operation_mode = SPDC_NO_OPERATION;
3017 mutex_unlock(&fb_data->queue_mutex);
3022 /* waveform loading to SPDC from memory */
3023 if (int_events & SPDC_IRQ_STA_LUT_DOWNLOAD) {
3024 if (is_lut_checksum_ok(fb_data)) {
3025 complete(&fb_data->lut_down);
3026 spdc_intr_stat_clear(fb_data,
3027 SPDC_IRQ_STA_LUT_DOWNLOAD);
3029 dev_dbg(fb_data->dev, "Lut checksum is err!\n");
3034 /* SPDC init setting IRQ */
3035 if (int_events & SPDC_IRQ_STA_TCON_INIT) {
3036 complete(&fb_data->init_finish);
3037 spdc_intr_stat_clear(fb_data, SPDC_IRQ_STA_TCON_INIT);
3042 spin_unlock_irqrestore(&fb_data->lock, flags);
3044 if (spdc_is_update_finish(fb_data)) {
3045 /* clear interrupt status */
3046 spdc_intr_stat_clear(fb_data, SPDC_IRQ_STA_FRAME_UPDATE);
3047 queue_work(fb_data->spdc_intr_workqueue,
3048 &fb_data->spdc_intr_work);
3054 static void spdc_intr_work_func(struct work_struct *work)
3056 mxc_spdc_t *fb_data =
3057 container_of(work, mxc_spdc_t, spdc_intr_work);
3058 struct mxcfb_rect *next_upd_region;
3059 struct update_marker_data *next_marker;
3060 struct update_marker_data *temp;
3061 struct update_data_list *next_upd, *temp_upd;
3063 /* Protect access to buffer queues and to update HW */
3064 mutex_lock(&fb_data->queue_mutex);
3066 /* Check to see if all updates have completed */
3067 if (list_empty(&fb_data->upd_pending_list) &&
3068 is_free_list_full(fb_data) &&
3069 (fb_data->cur_update == NULL)) {
3071 fb_data->updates_active = false;
3073 if (fb_data->pwrdown_delay != FB_POWERDOWN_DISABLE) {
3075 * Set variable to prevent overlapping
3076 * enable/disable requests
3078 fb_data->powering_down = true;
3080 /* Schedule task to disable SPDC HW until next update */
3081 schedule_delayed_work(&fb_data->spdc_done_work,
3082 msecs_to_jiffies(fb_data->pwrdown_delay));
3084 /* Reset counter to reduce chance of overflow */
3085 fb_data->order_cnt = 0;
3088 if (fb_data->waiting_for_idle)
3089 complete(&fb_data->updates_done);
3092 if (mxc_spdc_device_is_busy(fb_data)) {
3093 /* Can't submit another update until SPDC is idle */
3094 mutex_unlock(&fb_data->queue_mutex);
3099 * Were we waiting on working buffer?
3100 * If so, update queues and check for collisions
3102 if (fb_data->cur_update != NULL) {
3103 list_for_each_entry_safe(next_marker, temp,
3104 &fb_data->cur_update->update_desc->upd_marker_list,
3107 /* Del from per-update & full list */
3108 list_del_init(&next_marker->upd_list);
3109 list_del_init(&next_marker->full_list);
3111 /* Signal completion of update */
3112 dev_dbg(fb_data->dev,
3113 "Signaling marker %d\n",
3114 next_marker->update_marker);
3115 if (next_marker->waiting)
3116 complete(&next_marker->update_completion);
3121 /* Free marker list and update descriptor */
3122 kfree(fb_data->cur_update->update_desc);
3124 /* Add to free buffer list */
3125 list_add_tail(&fb_data->cur_update->list,
3126 &fb_data->upd_buf_free_list);
3128 if (fb_data->submit_upd_sta & SPDC_CONCUR_UPD) {
3129 fb_data->upd_preprocess_num = 0;
3130 fb_data->submit_upd_sta &= (~SPDC_CONCUR_UPD);
3133 /* free ACC update list */
3134 list_for_each_entry_safe(next_upd, temp_upd,
3135 &fb_data->upd_buf_preprocess_list, list) {
3136 next_marker = list_entry(
3137 (&next_upd->update_desc->upd_marker_list)->next,
3138 struct update_marker_data, upd_list);
3140 list_del_init(&next_marker->upd_list);
3141 list_del_init(&next_marker->full_list);
3143 /* Signal completion of update */
3144 dev_dbg(fb_data->dev,
3145 "Signaling marker %d\n",
3146 next_marker->update_marker);
3148 if (next_marker->waiting)
3149 complete(&next_marker->update_completion);
3154 list_del_init(&next_upd->list);
3155 /* Add to free buffer list */
3156 list_add_tail(&next_upd->list,
3157 &fb_data->upd_buf_free_list);
3158 kfree(next_upd->update_desc);
3161 /* Check to see if all updates have completed */
3162 if (list_empty(&fb_data->upd_pending_list) &&
3163 is_free_list_full(fb_data)) {
3165 fb_data->updates_active = false;
3167 if (fb_data->pwrdown_delay !=
3168 FB_POWERDOWN_DISABLE) {
3170 * Set variable to prevent overlapping
3171 * enable/disable requests
3173 fb_data->powering_down = true;
3175 /* Schedule SPDC disable */
3176 schedule_delayed_work(&fb_data->spdc_done_work,
3177 msecs_to_jiffies(fb_data->pwrdown_delay));
3179 /* Reset counter to reduce chance of overflow */
3180 fb_data->order_cnt = 0;
3183 if (fb_data->waiting_for_idle)
3184 complete(&fb_data->updates_done);
3187 /* Signal completion if submit workqueue was waiting on WB */
3188 if (fb_data->waiting_for_wb) {
3189 dev_dbg(fb_data->dev, "free update_res_free\n");
3190 complete(&fb_data->update_res_free);
3191 fb_data->waiting_for_wb = false;
3194 /* Clear current update */
3195 fb_data->cur_update = NULL;
3198 if (fb_data->upd_scheme != UPDATE_SCHEME_SNAPSHOT) {
3199 /* Queued update scheme processing */
3200 /* Schedule task to submit collision and pending update */
3201 if (!fb_data->powering_down)
3202 queue_work(fb_data->spdc_submit_workqueue,
3203 &fb_data->spdc_submit_work);
3205 /* Release buffer queues */
3206 mutex_unlock(&fb_data->queue_mutex);
3210 /* Snapshot update scheme processing */
3211 if (list_empty(&fb_data->upd_buf_queue)) {
3212 dev_dbg(fb_data->dev, "No pending updates.\n");
3214 /* No updates pending, so we are done */
3215 mutex_unlock(&fb_data->queue_mutex);
3218 dev_dbg(fb_data->dev, "Found a pending update!\n");
3220 /* Process next item in update list */
3221 fb_data->cur_update =
3222 list_entry(fb_data->upd_buf_queue.next,
3223 struct update_data_list, list);
3224 list_del_init(&fb_data->cur_update->list);
3227 /* program SPDC register and trigger to process buffer*/
3229 &fb_data->cur_update->update_desc->upd_data.update_region;
3230 fb_data->fresh_param.buf_addr.next_buf_phys_addr =
3231 fb_data->cur_update->phys_addr +
3232 (fb_data->cur_update->update_desc->spdc_offs / 2);
3234 fb_data->fresh_param.update_region.left = next_upd_region->left;
3235 fb_data->fresh_param.update_region.top = next_upd_region->top;
3236 fb_data->fresh_param.update_region.width = next_upd_region->width;
3237 fb_data->fresh_param.update_region.height = next_upd_region->height;
3238 fb_data->fresh_param.temper =
3239 fb_data->cur_update->update_desc->upd_data.temp;
3240 fb_data->fresh_param.wave_mode =
3241 fb_data->cur_update->update_desc->upd_data.waveform_mode;
3242 spdc_submit_update(fb_data);
3244 mutex_unlock(&fb_data->queue_mutex);
3252 static ssize_t show_update(struct device *device,
3253 struct device_attribute *attr, char *buf) {
3254 struct fb_info *info = dev_get_drvdata(device);
3255 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
3257 return sprintf(buf, "mode%d\n", fb_data->fresh_param.wave_mode);
3260 static ssize_t store_update(struct device *device,
3261 struct device_attribute *attr,
3262 const char *buf, size_t count)
3264 struct mxcfb_update_data update;
3265 struct fb_info *info = dev_get_drvdata(device);
3266 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
3267 if (strncmp(buf, "direct", 6) == 0)
3268 update.waveform_mode = fb_data->wv_modes.mode_du;
3269 else if (strncmp(buf, "gc16", 4) == 0)
3270 update.waveform_mode = fb_data->wv_modes.mode_gc16;
3271 else if (strncmp(buf, "gc4", 3) == 0)
3272 update.waveform_mode = fb_data->wv_modes.mode_gc4;
3273 else if (strncmp(buf, "init", 4) == 0)
3274 update.waveform_mode = fb_data->wv_modes.mode_init;
3275 else if (strncmp(buf, "gu", 2) == 0)
3276 update.waveform_mode = SPDC_WAV_MODE_1;
3277 else if (strncmp(buf, "auto", 4) == 0)
3278 update.waveform_mode = WAVEFORM_MODE_AUTO;
3280 /* Now, request full screen update */
3281 update.update_region.left = 0;
3282 update.update_region.width = fb_data->spdc_fb_var.xres;
3283 update.update_region.top = 0;
3284 update.update_region.height = fb_data->spdc_fb_var.yres;
3285 update.update_mode = UPDATE_MODE_FULL;
3286 update.temp = SPDC_DEFAULT_TEMP;
3287 update.update_marker = 0;
3289 dev_dbg(fb_data->dev, "rotation:%d, gray:%d\n",
3290 fb_data->spdc_fb_var.rotate, fb_data->spdc_fb_var.grayscale);
3292 mxc_spdc_fb_send_update(&update, info);
3297 static ssize_t fresh_show(struct device *device, struct device_attribute *attr,
3300 struct fb_info *info = dev_get_drvdata(device);
3301 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
3303 return sprintf(buf, "%d\n", fb_data->operation_mode);
3306 static ssize_t fresh_store(struct device *device, struct device_attribute *attr,
3307 const char *buf, size_t count)
3309 struct fb_info *info = dev_get_drvdata(device);
3310 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
3313 ret = kstrtoint(buf, 10, &operation);
3317 if (operation == SPDC_DEEP_REFRESH)
3318 fb_data->is_deep_fresh = true;
3319 fb_data->operation_mode = operation;
3320 if (operation > SPDC_NO_OPERATION &&
3321 operation < SPDC_FULL_REFRESH)
3322 mxc_operaton_update(fb_data);
3324 mxc_spdc_refresh_display(fb_data);
3329 static ssize_t temp_show(struct device *device,
3330 struct device_attribute *attr, char *buf)
3332 struct fb_info *info = dev_get_drvdata(device);
3333 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
3336 temp = fb_data->fresh_param.temper >> 1;
3337 return sprintf(buf, "%d\n", temp);
3340 static ssize_t initset_show(struct device *device,
3341 struct device_attribute *attr, char *buf)
3343 struct fb_info *info = dev_get_drvdata(device);
3344 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
3347 get_panel_init_set(&fb_data->panel_set, &init_val);
3348 return sprintf(buf, "%x\n", init_val);
3351 static ssize_t concurrency_show(struct device *device,
3352 struct device_attribute *attr, char *buf)
3354 struct fb_info *info = dev_get_drvdata(device);
3355 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
3358 temp = (fb_data->fresh_param.concur ? 1 : 0);
3359 return sprintf(buf, "%d\n", temp);
3362 static ssize_t concurrency_update(struct device *device,
3363 struct device_attribute *attr, const char *buf, size_t count)
3365 struct fb_info *info = dev_get_drvdata(device);
3366 mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
3369 ret = kstrtoint(buf, 10, &concur);
3373 if (fb_data->fresh_param.concur != concur) {
3374 fb_data->fresh_param.concur = concur;
3375 spdc_set_update_concurrency(fb_data);
3381 static DEVICE_ATTR(store_update, 0644, show_update, store_update);
3382 static DEVICE_ATTR(fresh, 0644, fresh_show, fresh_store);
3383 static DEVICE_ATTR(temp, 0644, temp_show, NULL);
3384 static DEVICE_ATTR(initset, 0644, initset_show, NULL);
3385 static DEVICE_ATTR(concurrency, 0644, concurrency_show, concurrency_update);
3387 static struct attribute *spdc_attributes[] = {
3388 &dev_attr_store_update.attr,
3389 &dev_attr_fresh.attr,
3390 &dev_attr_temp.attr,
3391 &dev_attr_initset.attr,
3392 &dev_attr_concurrency.attr,
3396 static const struct attribute_group spdc_attr_group = {
3397 .attrs = spdc_attributes,
3400 static int __devinit mxc_spdc_fb_probe(struct platform_device *pdev)
3402 struct fb_info *info;
3403 mxc_spdc_t *fb_data;
3404 struct resource *res, *mem;
3405 struct fb_videomode *vmode;
3406 int xres_virt, yres_virt, buf_size;
3407 int xres_virt_rot, yres_virt_rot, pix_size_rot;
3408 struct fb_var_screeninfo *var_info;
3409 struct fb_fix_screeninfo *fix_info;
3410 struct pxp_config_data *pxp_conf;
3411 struct pxp_proc_data *proc_data;
3412 struct scatterlist *sg;
3413 struct update_data_list *upd_list;
3414 struct update_data_list *plist, *temp_list;
3415 char *options, *opt;
3416 char *panel_str = NULL;
3417 char name[] = "mxcspdcfb";
3418 unsigned long x_mem_size = 0;
3422 fb_data = (mxc_spdc_t *)framebuffer_alloc(sizeof(mxc_spdc_t),
3429 info = &fb_data->info;
3430 fb_data->dev = &pdev->dev;
3431 platform_set_drvdata(pdev, fb_data);
3433 fb_data->pdata = pdev->dev.platform_data;
3434 if ((fb_data->pdata == NULL) || (fb_data->pdata->num_modes < 1)
3435 || (fb_data->pdata->spdc_mode == NULL)
3436 || (fb_data->pdata->spdc_mode->vmode == NULL)) {
3441 /*get panel para from command*/
3442 if (fb_get_options(name, &options)) {
3447 while ((opt = strsep(&options, ",")) != NULL) {
3450 if (!strncmp(opt, "bpp=", 4)) {
3451 if (kstrtoint(opt + 4, 0,
3452 &fb_data->default_bpp) < 0)
3453 fb_data->default_bpp = 0;
3454 } else if (!strncmp(opt, "x_mem=", 6))
3455 x_mem_size = memparse(opt + 6, NULL);
3460 if (!fb_data->default_bpp)
3461 fb_data->default_bpp = SPDC_DEFAULT_BPP;
3463 /* Set default (first defined mode) for a match */
3464 mxc_spdc_find_match_mode(fb_data);
3467 for (i = 0; i < fb_data->pdata->num_modes; i++)
3468 if (!strcmp(fb_data->pdata->spdc_mode[i].vmode->name,
3471 &fb_data->pdata->spdc_mode[i];
3474 vmode = fb_data->cur_mode->vmode;
3476 /* Allocate color map for the FB */
3478 ret = fb_alloc_cmap(&info->cmap, cmap_size, 0);
3483 * GPU alignment restrictions dictate framebuffer parameters:
3484 * - 32-byte alignment for buffer width
3485 * - 128-byte alignment for buffer height
3486 * => 4K buffer alignment for buffer start
3488 xres_virt = ALIGN(vmode->xres, 32);
3489 yres_virt = ALIGN(vmode->yres, 128);
3490 fb_data->max_pix_size = PAGE_ALIGN(xres_virt * yres_virt);
3493 * Have to check to see if aligned buffer size when rotated
3494 * is bigger than when not rotated, and use the max
3496 xres_virt_rot = ALIGN(vmode->yres, 32);
3497 yres_virt_rot = ALIGN(vmode->xres, 128);
3498 pix_size_rot = PAGE_ALIGN(xres_virt_rot * yres_virt_rot);
3499 fb_data->max_pix_size = (fb_data->max_pix_size > pix_size_rot) ?
3500 fb_data->max_pix_size : pix_size_rot;
3501 buf_size = fb_data->max_pix_size * fb_data->default_bpp/8;
3503 /* Compute the number of screens needed based on X memory requested */
3504 if (x_mem_size > 0) {
3505 fb_data->num_screens = DIV_ROUND_UP(x_mem_size, buf_size);
3506 if (fb_data->num_screens < NUM_SCREENS_MIN)
3507 fb_data->num_screens = NUM_SCREENS_MIN;
3508 else if (buf_size * fb_data->num_screens > SZ_16M)
3509 fb_data->num_screens = SZ_16M / buf_size;
3511 fb_data->num_screens = NUM_SCREENS_MIN;
3513 fb_data->map_size = buf_size * fb_data->num_screens;
3514 dev_dbg(&pdev->dev, "memory allocate: %d\n", fb_data->map_size);
3517 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3519 dev_err(&pdev->dev, "failed to get memory register\n");
3524 mem = request_mem_region(res->start, resource_size(res), pdev->name);
3526 dev_err(&pdev->dev, "failed to get memory region\n");
3531 fb_data->hwp = ioremap(res->start, SZ_4K);
3532 if (fb_data->hwp == NULL) {
3533 dev_err(&pdev->dev, "ioremap registers failed\n");
3538 /* Allocate FB memory */
3539 fb_data->virt_start = dma_alloc_writecombine(&pdev->dev,
3540 fb_data->map_size, &fb_data->phys_start, GFP_DMA);
3541 if (fb_data->virt_start == NULL) {
3542 dev_err(&pdev->dev, "probe err - dma_alloc for framebuffer\n");
3547 var_info = &info->var;
3548 var_info->activate = FB_ACTIVATE_TEST;
3549 var_info->bits_per_pixel = fb_data->default_bpp;
3550 var_info->xres = vmode->xres;
3551 var_info->yres = vmode->yres;
3552 var_info->xres_virtual = xres_virt;
3553 var_info->yres_virtual = yres_virt * fb_data->num_screens;
3554 var_info->pixclock = vmode->pixclock;
3555 var_info->left_margin = vmode->left_margin;
3556 var_info->right_margin = vmode->right_margin;
3557 var_info->upper_margin = vmode->upper_margin;
3558 var_info->lower_margin = vmode->lower_margin;
3559 var_info->hsync_len = vmode->hsync_len;
3560 var_info->vsync_len = vmode->vsync_len;
3561 var_info->vmode = FB_VMODE_NONINTERLACED;
3563 switch (fb_data->default_bpp) {
3566 var_info->red.offset = 16;
3567 var_info->red.length = 8;
3568 var_info->green.offset = 8;
3569 var_info->green.length = 8;
3570 var_info->blue.offset = 0;
3571 var_info->blue.length = 8;
3574 var_info->red.offset = 11;
3575 var_info->red.length = 5;
3576 var_info->green.offset = 5;
3577 var_info->green.length = 6;
3578 var_info->blue.offset = 0;
3579 var_info->blue.length = 5;
3582 var_info->grayscale = GRAYSCALE_8BIT;
3584 var_info->red.length = 8;
3585 var_info->red.offset = 0;
3586 var_info->red.msb_right = 0;
3587 var_info->green.length = 8;
3588 var_info->green.offset = 0;
3589 var_info->green.msb_right = 0;
3590 var_info->blue.length = 8;
3591 var_info->blue.offset = 0;
3592 var_info->blue.msb_right = 0;
3595 var_info->grayscale = GRAYSCALE_4BIT;
3597 var_info->red.length = 4;
3598 var_info->red.offset = 0;
3599 var_info->red.msb_right = 0;
3600 var_info->green.length = 4;
3601 var_info->green.offset = 0;
3602 var_info->green.msb_right = 0;
3603 var_info->blue.length = 4;
3604 var_info->blue.offset = 0;
3605 var_info->blue.msb_right = 0;
3608 dev_err(&pdev->dev, "unsupported bit-width:%d\n",
3609 fb_data->default_bpp);
3611 goto release_dma_fb;
3614 fix_info = &info->fix;
3615 strcpy(fix_info->id, SPDC_DRIVER_NAME);
3616 fix_info->type = FB_TYPE_PACKED_PIXELS;
3617 fix_info->visual = FB_VISUAL_TRUECOLOR;
3618 fix_info->xpanstep = 0;
3619 fix_info->ypanstep = 0;
3620 fix_info->ywrapstep = 0;
3621 fix_info->accel = FB_ACCEL_NONE;
3622 fix_info->smem_start = fb_data->phys_start;
3623 fix_info->smem_len = fb_data->map_size;
3624 fix_info->ypanstep = 0;
3626 /* Set up FB info */
3627 fb_data->native_width = vmode->xres;
3628 fb_data->native_height = vmode->yres;
3629 info->screen_base = fb_data->virt_start;
3630 info->screen_size = info->fix.smem_len;
3631 info->fbops = &mxc_spdc_fb_ops;
3632 info->var.activate = FB_ACTIVATE_NOW;
3633 info->pseudo_palette = fb_data->pseudo_palette;
3634 info->flags = FBINFO_FLAG_DEFAULT;
3636 mxc_spdc_fb_set_fix(info);
3638 /* use the same AXI and PIX clock source */
3639 fb_data->spdc_clk_axi = clk_get(fb_data->dev, "epdc_axi");
3640 if (IS_ERR(fb_data->spdc_clk_axi)) {
3641 dev_err(&pdev->dev, "Unable to get AXI clk."
3642 "err = 0x%x\n", (int)fb_data->spdc_clk_axi);
3644 goto release_dma_fb;
3646 fb_data->spdc_clk_pix = clk_get(fb_data->dev, "epdc_pix");
3647 if (IS_ERR(fb_data->spdc_clk_pix)) {
3648 dev_err(&pdev->dev, "Unable to get pix clk."
3649 "err = 0x%x\n", (int)fb_data->spdc_clk_pix);
3651 goto release_dma_fb;
3655 * Initialize update list and allocate buffer.
3657 INIT_LIST_HEAD(&fb_data->upd_pending_list);
3658 INIT_LIST_HEAD(&fb_data->upd_buf_queue);
3659 INIT_LIST_HEAD(&fb_data->upd_buf_free_list);
3660 INIT_LIST_HEAD(&fb_data->upd_buf_preprocess_list);
3661 INIT_LIST_HEAD(&fb_data->full_marker_list);
3663 fb_data->max_num_updates = SPDC_MAX_NUM_UPDATES;
3664 fb_data->max_num_buffers = SPDC_MAX_NUM_BUFFERS;
3666 /* Allocate free buffers */
3667 for (i = 0; i < fb_data->max_num_updates; i++) {
3668 upd_list = kzalloc(sizeof(*upd_list), GFP_KERNEL);
3669 if (upd_list == NULL) {
3671 goto release_dma_fb;
3674 /* Add newly allocated buffer to free list */
3675 list_add(&upd_list->list, &fb_data->upd_buf_free_list);
3678 /* Allocate PXP output buffer */
3679 fb_data->virt_addr_updbuf =
3680 kzalloc(sizeof(void *) * fb_data->max_num_buffers, GFP_KERNEL);
3681 fb_data->phys_addr_updbuf =
3682 kzalloc(sizeof(dma_addr_t) * fb_data->max_num_buffers,
3684 for (i = 0; i < fb_data->max_num_buffers; i++) {
3686 * Allocate memory for PxP output buffer.
3687 * Output raw data is Y4 format.
3688 * Each update buffer is 1/2 byte per pixel, and can
3689 * be as big as the full-screen frame buffer
3691 fb_data->virt_addr_updbuf[i] =
3692 dma_alloc_coherent(fb_data->info.device,
3693 fb_data->max_pix_size / 2,
3694 &fb_data->phys_addr_updbuf[i], GFP_DMA);
3695 if (fb_data->virt_addr_updbuf[i] == NULL) {
3697 goto release_freebuf_lists;
3700 /* Counter indicating which update buffer should be used next. */
3701 fb_data->upd_buffer_num = 0;
3703 /* Allocate memory for partical process region buffer.
3704 * Output raw data is Y4 format.
3706 fb_data->virt_addr_copybuf =
3707 dma_alloc_coherent(fb_data->info.device,
3708 fb_data->max_pix_size / 2,
3709 &fb_data->phys_addr_copybuf, GFP_DMA);
3710 if (fb_data->virt_addr_copybuf == NULL) {
3712 goto release_output_buf;
3715 /* Allocate next & current & privious & count & lut buffers.
3716 * next buffer size is Y4 raw data
3718 fb_data->next_buf_size =
3719 (fb_data->map_size / fb_data->num_screens) >> 1;
3720 fb_data->virt_next_buf =
3721 dma_alloc_coherent(&pdev->dev, fb_data->next_buf_size,
3722 &fb_data->phy_next_buf, GFP_DMA);
3723 if (fb_data->virt_next_buf == NULL) {
3724 dev_err(&pdev->dev, "Can't allocate mem for next buf!\n");
3726 goto release_copy_buf;
3729 fb_data->current_buf_size =
3730 (fb_data->map_size / fb_data->num_screens) >> 1;
3731 fb_data->virt_current_buf =
3732 dma_alloc_coherent(&pdev->dev, fb_data->current_buf_size,
3733 &fb_data->phy_current_buf, GFP_DMA);
3734 if (fb_data->virt_current_buf == NULL) {
3735 dev_err(&pdev->dev, "Can't allocate mem for current buf!\n");
3737 goto release_next_buf;
3740 fb_data->pre_buf_size =
3741 (fb_data->map_size / fb_data->num_screens) >> 1;
3742 fb_data->virt_pre_buf =
3743 dma_alloc_coherent(&pdev->dev, fb_data->pre_buf_size,
3744 &fb_data->phy_pre_buf, GFP_DMA);
3745 if (fb_data->virt_pre_buf == NULL) {
3746 dev_err(&pdev->dev, "Can't allocate mem for current buf!\n");
3748 goto release_current_buf;
3751 fb_data->cnt_buf_size = info->var.xres * info->var.yres;
3752 fb_data->virt_cnt_buf =
3753 dma_alloc_coherent(&pdev->dev, fb_data->cnt_buf_size,
3754 &fb_data->phy_cnt_buf, GFP_DMA);
3755 if (fb_data->virt_cnt_buf == NULL) {
3756 dev_err(&pdev->dev, "Can't allocate mem for current buf!\n");
3758 goto release_pre_buf;
3761 fb_data->lut_buf_size = SZ_1M;
3762 fb_data->virt_lut_buf =
3763 dma_alloc_coherent(&pdev->dev, fb_data->lut_buf_size,
3764 &fb_data->phy_lut_buf, GFP_DMA);
3765 if (fb_data->virt_lut_buf == NULL) {
3766 dev_err(&pdev->dev, "Can't allocate mem for current buf!\n");
3768 goto release_cnt_buf;
3771 /* Initialize SPDC pins */
3772 if (fb_data->pdata->get_pins)
3773 fb_data->pdata->get_pins();
3775 fb_data->hw_ready = false;
3776 fb_data->hw_initializing = false;
3779 * Set default waveform mode values.
3780 * Should be overwritten via ioctl.
3782 fb_data->wv_modes.mode_init = SPDC_WAV_MODE_DEFAULT;
3783 fb_data->wv_modes.mode_du = SPDC_WAV_MODE_2;
3784 fb_data->wv_modes.mode_gc4 = SPDC_WAV_MODE_2;
3785 fb_data->wv_modes.mode_gc8 = SPDC_WAV_MODE_1;
3786 fb_data->wv_modes.mode_gc16 = SPDC_WAV_MODE_1;
3787 fb_data->wv_modes.mode_gc32 = SPDC_WAV_MODE_1;
3789 fb_data->auto_mode = AUTO_UPDATE_MODE_REGION_MODE;
3790 fb_data->upd_scheme = UPDATE_SCHEME_QUEUE_AND_MERGE;
3791 fb_data->spdc_fb_var = *var_info;
3792 fb_data->fb_offset = 0;
3794 fb_data->blank = FB_BLANK_UNBLANK;
3795 fb_data->powering_down = false;
3796 fb_data->power_state = POWER_STATE_OFF;
3797 fb_data->pwrdown_delay = 0;
3798 fb_data->cur_update = NULL;
3799 fb_data->waiting_for_idle = false;
3800 fb_data->order_cnt = 0;
3801 fb_data->waiting_for_wb = false;
3802 fb_data->wait_for_powerdown = false;
3803 fb_data->updates_active = false;
3805 spin_lock_init(&fb_data->lock);
3806 mutex_init(&fb_data->queue_mutex);
3807 mutex_init(&fb_data->pxp_mutex);
3808 mutex_init(&fb_data->power_mutex);
3809 init_completion(&fb_data->lut_down);
3810 init_completion(&fb_data->init_finish);
3811 init_completion(&fb_data->update_finish);
3812 INIT_DELAYED_WORK(&fb_data->spdc_done_work, spdc_done_work_func);
3814 fb_data->spdc_submit_workqueue = alloc_workqueue("SPDC Submit",
3815 WQ_MEM_RECLAIM | WQ_HIGHPRI |
3816 WQ_CPU_INTENSIVE | WQ_UNBOUND, 1);
3817 INIT_WORK(&fb_data->spdc_submit_work, spdc_submit_work_func);
3818 fb_data->spdc_intr_workqueue = alloc_workqueue("SPDC Interrupt",
3819 WQ_MEM_RECLAIM | WQ_HIGHPRI |
3820 WQ_CPU_INTENSIVE | WQ_UNBOUND, 1);
3821 INIT_WORK(&fb_data->spdc_intr_work, spdc_intr_work_func);
3823 /* Retrieve spdc IRQ num */
3824 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
3826 dev_err(&pdev->dev, "cannot get IRQ resource\n");
3828 goto release_lut_buf;
3830 fb_data->spdc_irq = res->start;
3831 ret = request_irq(fb_data->spdc_irq, mxc_spdc_irq_handler, 0,
3834 dev_err(&pdev->dev, "request_irq (%d) failed with error %d\n",
3835 fb_data->spdc_irq, ret);
3837 goto release_lut_buf;
3840 /* define deferred io */
3841 info->fbdefio = &mxc_spdc_fb_defio;
3842 #ifdef CONFIG_FB_MXC_SIPIX_AUTO_UPDATE_MODE
3843 fb_deferred_io_init(info);
3846 /* get pmic regulators */
3847 fb_data->display_regulator = regulator_get(NULL, "DISPLAY");
3848 if (IS_ERR(fb_data->display_regulator)) {
3849 dev_err(&pdev->dev, "Unable to get display PMIC regulator."
3850 "err = 0x%x\n", (int)fb_data->display_regulator);
3854 fb_data->vcom_regulator = regulator_get(NULL, "VCOM");
3855 if (IS_ERR(fb_data->vcom_regulator)) {
3856 regulator_put(fb_data->display_regulator);
3857 dev_err(&pdev->dev, "Unable to get VCOM regulator."
3858 "err = 0x%x\n", (int)fb_data->vcom_regulator);
3860 goto release_regulator1;
3862 fb_data->v3p3_regulator = regulator_get(NULL, "V3P3");
3863 if (IS_ERR(fb_data->v3p3_regulator)) {
3864 regulator_put(fb_data->vcom_regulator);
3865 regulator_put(fb_data->display_regulator);
3866 dev_err(&pdev->dev, "Unable to get V3P3 regulator."
3867 "err = 0x%x\n", (int)fb_data->vcom_regulator);
3869 goto release_regulator2;
3873 * Fill out PxP config data structure based on FB info and
3874 * processing tasks required
3876 pxp_conf = &fb_data->pxp_conf;
3877 proc_data = &pxp_conf->proc_data;
3879 /* Initialize non-channel-specific PxP parameters */
3880 proc_data->drect.left = proc_data->srect.left = 0;
3881 proc_data->drect.top = proc_data->srect.top = 0;
3882 proc_data->drect.width = fb_data->info.var.xres;
3883 proc_data->srect.width = fb_data->info.var.xres;
3884 proc_data->drect.height = fb_data->info.var.yres;
3885 proc_data->srect.height = fb_data->info.var.yres;
3886 proc_data->scaling = 0;
3887 proc_data->hflip = 0;
3888 proc_data->vflip = 0;
3889 proc_data->rotate = 0;
3890 proc_data->bgcolor = 0;
3891 proc_data->overlay_state = 0;
3892 proc_data->lut_transform = PXP_LUT_NONE;
3893 proc_data->lut_map = NULL;
3896 * We initially configure PxP for RGB->YUV conversion,
3897 * and only write out Y component of the result.
3901 * Initialize S0 channel parameters
3902 * Parameters should match FB format/width/height
3904 pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB565;
3905 pxp_conf->s0_param.width = fb_data->info.var.xres_virtual;
3906 pxp_conf->s0_param.height = fb_data->info.var.yres;
3907 pxp_conf->s0_param.color_key = -1;
3908 pxp_conf->s0_param.color_key_enable = false;
3911 * Initialize OL0 channel parameters
3912 * No overlay will be used for PxP operation
3914 for (i = 0; i < 8; i++) {
3915 pxp_conf->ol_param[i].combine_enable = false;
3916 pxp_conf->ol_param[i].width = 0;
3917 pxp_conf->ol_param[i].height = 0;
3918 pxp_conf->ol_param[i].pixel_fmt = PXP_PIX_FMT_RGB565;
3919 pxp_conf->ol_param[i].color_key_enable = false;
3920 pxp_conf->ol_param[i].color_key = -1;
3921 pxp_conf->ol_param[i].global_alpha_enable = false;
3922 pxp_conf->ol_param[i].global_alpha = 0;
3923 pxp_conf->ol_param[i].local_alpha_enable = false;
3927 * Initialize Output channel parameters
3928 * Output is Y-only greyscale
3929 * Output width/height will vary based on update region size
3931 pxp_conf->out_param.width = fb_data->info.var.xres;
3932 pxp_conf->out_param.height = fb_data->info.var.yres;
3933 pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_GY04;
3934 pxp_conf->out_param.stride = pxp_conf->out_param.width;
3936 /* Initialize color map for conversion of 8-bit gray pixels */
3937 fb_data->pxp_conf.proc_data.lut_map = kmalloc(256, GFP_KERNEL);
3938 if (fb_data->pxp_conf.proc_data.lut_map == NULL) {
3939 dev_err(&pdev->dev, "Can't allocate mem for lut map!\n");
3941 goto release_regulator3;
3943 for (i = 0; i < 256; i++)
3944 fb_data->pxp_conf.proc_data.lut_map[i] = i;
3946 fb_data->pxp_conf.proc_data.lut_map_updated = true;
3949 * Ensure this is set to NULL here...we will initialize pxp_chan
3950 * later in our thread.
3952 fb_data->pxp_chan = NULL;
3954 /* Initialize Scatter-gather list containing 2 buffer addresses. */
3956 sg_init_table(sg, 2);
3959 * For use in PxP transfers:
3960 * sg[0] holds the FB buffer pointer
3961 * sg[1] holds the Output buffer pointer (configured before TX request)
3963 sg_dma_address(&sg[0]) = info->fix.smem_start;
3964 sg_set_page(&sg[0], virt_to_page(info->screen_base),
3965 info->fix.smem_len, offset_in_page(info->screen_base));
3968 ret = register_framebuffer(info);
3971 "register framebuffer failed\n");
3972 goto release_lutmap;
3975 ret = sysfs_create_group(&info->device->kobj, &spdc_attr_group);
3977 dev_err(&pdev->dev, "Unable to create file from fb_attrs\n");
3979 /* use for spdc test */
3980 g_fb_data = fb_data;
3983 spdc_fb_dev_init(fb_data);
3985 /*detect spdc epd disp & tcon version*/
3986 get_spdc_version(fb_data);
3991 kfree(fb_data->pxp_conf.proc_data.lut_map);
3993 regulator_put(fb_data->v3p3_regulator);
3995 regulator_put(fb_data->vcom_regulator);
3997 regulator_put(fb_data->display_regulator);
3999 free_irq(fb_data->spdc_irq, fb_data);
4001 dma_free_coherent(&pdev->dev, fb_data->pre_buf_size,
4002 fb_data->virt_lut_buf, fb_data->phy_lut_buf);
4004 dma_free_coherent(&pdev->dev, fb_data->cnt_buf_size,
4005 fb_data->virt_cnt_buf, fb_data->phy_cnt_buf);
4007 dma_free_coherent(&pdev->dev, fb_data->pre_buf_size,
4008 fb_data->virt_pre_buf, fb_data->phy_pre_buf);
4009 release_current_buf:
4010 dma_free_coherent(&pdev->dev, fb_data->current_buf_size,
4011 fb_data->virt_current_buf, fb_data->phy_current_buf);
4013 dma_free_coherent(&pdev->dev, fb_data->next_buf_size,
4014 fb_data->virt_next_buf, fb_data->phy_next_buf);
4016 dma_free_writecombine(&pdev->dev, fb_data->max_pix_size / 2,
4017 fb_data->virt_addr_copybuf, fb_data->phys_addr_copybuf);
4019 for (i = 0; i < fb_data->max_num_buffers; i++)
4020 if (fb_data->virt_addr_updbuf[i] != NULL)
4021 dma_free_writecombine(&pdev->dev,
4022 fb_data->max_pix_size / 2, fb_data->virt_addr_updbuf[i],
4023 fb_data->phys_addr_updbuf[i]);
4024 if (fb_data->virt_addr_updbuf != NULL)
4025 kfree(fb_data->virt_addr_updbuf);
4026 if (fb_data->phys_addr_updbuf != NULL)
4027 kfree(fb_data->phys_addr_updbuf);
4028 release_freebuf_lists:
4029 list_for_each_entry_safe(plist, temp_list, &fb_data->upd_buf_free_list,
4031 list_del(&plist->list);
4035 dma_free_writecombine(&pdev->dev,
4036 fb_data->map_size, fb_data->virt_start, fb_data->phys_start);
4038 iounmap(fb_data->hwp);
4040 release_resource(mem);
4042 fb_dealloc_cmap(&info->cmap);
4044 framebuffer_release(info);
4049 static int mxc_spdc_fb_remove(struct platform_device *pdev)
4051 struct update_data_list *plist, *temp_list;
4052 mxc_spdc_t *fb_data = platform_get_drvdata(pdev);
4053 struct fb_info *info = &fb_data->info;
4056 mxc_spdc_fb_blank(FB_BLANK_POWERDOWN, &fb_data->info);
4058 flush_workqueue(fb_data->spdc_submit_workqueue);
4059 destroy_workqueue(fb_data->spdc_submit_workqueue);
4061 regulator_put(fb_data->display_regulator);
4062 regulator_put(fb_data->vcom_regulator);
4063 regulator_put(fb_data->v3p3_regulator);
4065 for (i = 0; i < fb_data->max_num_buffers; i++)
4066 if (fb_data->virt_addr_updbuf[i] != NULL)
4067 dma_free_writecombine(&pdev->dev,
4068 fb_data->max_pix_size,
4069 fb_data->virt_addr_updbuf[i],
4070 fb_data->phys_addr_updbuf[i]);
4071 if (fb_data->virt_addr_updbuf != NULL)
4072 kfree(fb_data->virt_addr_updbuf);
4073 if (fb_data->phys_addr_updbuf != NULL)
4074 kfree(fb_data->phys_addr_updbuf);
4076 /* free output temporary buffer */
4077 dma_free_writecombine(&pdev->dev, fb_data->max_pix_size / 2,
4078 fb_data->virt_addr_copybuf, fb_data->phys_addr_copybuf);
4080 list_for_each_entry_safe(plist, temp_list,
4081 &fb_data->upd_buf_free_list,
4083 list_del(&plist->list);
4087 #if defined(CONFIG_FB_MXC_SIPIX_AUTO_UPDATE_MODE)
4088 fb_deferred_io_cleanup(&fb_data->info);
4091 /* free frame buffer */
4092 dma_free_writecombine(&pdev->dev, fb_data->map_size,
4093 info->screen_base, fb_data->phys_start);
4095 /* free SPDC hw allocate buffer */
4096 dma_free_coherent(&pdev->dev, fb_data->next_buf_size,
4097 fb_data->virt_next_buf, fb_data->phy_next_buf);
4098 dma_free_coherent(&pdev->dev, fb_data->current_buf_size,
4099 fb_data->virt_current_buf, fb_data->phy_current_buf);
4100 dma_free_coherent(&pdev->dev, fb_data->pre_buf_size,
4101 fb_data->virt_pre_buf, fb_data->phy_pre_buf);
4102 dma_free_coherent(&pdev->dev, fb_data->cnt_buf_size,
4103 fb_data->virt_cnt_buf, fb_data->phy_cnt_buf);
4104 dma_free_coherent(&pdev->dev, fb_data->pre_buf_size,
4105 fb_data->virt_lut_buf, fb_data->phy_lut_buf);
4107 sysfs_remove_group(&info->device->kobj, &spdc_attr_group);
4108 unregister_framebuffer(info);
4110 if (fb_data->pdata->put_pins)
4111 fb_data->pdata->put_pins();
4113 free_irq(fb_data->spdc_irq, fb_data);
4114 iounmap(fb_data->hwp);
4116 fb_dealloc_cmap(&info->cmap);
4118 framebuffer_release(info);
4119 platform_set_drvdata(pdev, NULL);
4125 static int mxc_spdc_fb_suspend(struct platform_device *pdev,
4128 mxc_spdc_t *data = platform_get_drvdata(pdev);
4131 ret = mxc_spdc_fb_blank(FB_BLANK_POWERDOWN, &data->info);
4136 static int mxc_spdc_fb_resume(struct platform_device *pdev)
4138 mxc_spdc_t *data = platform_get_drvdata(pdev);
4140 mxc_spdc_fb_blank(FB_BLANK_UNBLANK, &data->info);
4144 #define mxc_spdc_fb_suspend NULL
4145 #define mxc_spdc_fb_resume NULL
4148 static struct platform_driver mxc_spdc_fb_driver = {
4149 .probe = mxc_spdc_fb_probe,
4150 .remove = mxc_spdc_fb_remove,
4151 .suspend = mxc_spdc_fb_suspend,
4152 .resume = mxc_spdc_fb_resume,
4154 .name = SPDC_DRIVER_NAME,
4155 .owner = THIS_MODULE,
4159 static int __init mxc_spdc_fb_init(void)
4161 return platform_driver_register(&mxc_spdc_fb_driver);
4163 late_initcall(mxc_spdc_fb_init);
4165 static void __exit mxc_spdc_fb_exit(void)
4167 platform_driver_unregister(&mxc_spdc_fb_driver);
4169 module_exit(mxc_spdc_fb_exit);
4171 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
4172 MODULE_DESCRIPTION("MXC SPDC framebuffer driver");
4173 MODULE_LICENSE("GPL");
4174 MODULE_SUPPORTED_DEVICE("fb");