]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/video/mxc/mxc_spdc_fb.c
ENGR00211679 - SPDC : fix mode4 fresh issue.
[karo-tx-linux.git] / drivers / video / mxc / mxc_spdc_fb.c
1 /*
2  * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved.
3  *
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.
8  *
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.
13  *
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
17  *
18  */
19 /*
20  * Based on MXC EPDC Driver, Freescale Semiconductor, Inc. All Rights Reserved.
21  */
22
23 #include "mxc_spdc_fb.h"
24
25 #define MERGE_OK        0
26 #define MERGE_FAIL      1
27 #define MERGE_BLOCK     2
28
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
35
36 #define INIT_UPDATE_MARKER      0x12345678
37 #define PAN_UPDATE_MARKER       0x12345679
38
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
44
45 mxc_spdc_t *g_fb_data;
46
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);
51
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},
79 };
80
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},
108 };
109
110 static void get_panel_init_set(struct imx_spdc_panel_init_set*
111                                         panel_set, u32 *val)
112 {
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);
122 }
123
124 static inline void spdc_intr_enable(mxc_spdc_t *fb_data, u32 int_type)
125 {
126         u32 status;
127
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);
131 }
132
133 static bool spdc_is_update_finish(mxc_spdc_t *fb_data)
134 {
135         u32 val =  __raw_readl(fb_data->hwp + SPDC_INT_STA_CLR);
136         bool is_finish = (val & SPDC_IRQ_STA_FRAME_UPDATE) ? true : false;
137
138         return is_finish;
139 }
140
141 static int spdc_get_intr_stat(mxc_spdc_t *fb_data)
142 {
143         u32 status = __raw_readl(fb_data->hwp + SPDC_INT_STA_CLR);
144         return status & 0xF;
145 }
146
147 static inline void
148 spdc_intr_stat_clear(mxc_spdc_t *fb_data, u32 int_type)
149 {
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);
153 }
154
155 static inline void spdc_set_nextbuf_addr(mxc_spdc_t *fb_data)
156 {
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);
160 }
161
162 static inline void spdc_set_curbuf_addr(mxc_spdc_t *fb_data)
163 {
164         u32 addr = fb_data->fresh_param.buf_addr.cur_buf_phys_addr;
165         __raw_writel(addr, fb_data->hwp + SPDC_CURRENT_BUF);
166 }
167
168 static inline void spdc_set_prebuf_addr(mxc_spdc_t *fb_data)
169 {
170         u32 addr = fb_data->fresh_param.buf_addr.pre_buf_phys_addr;
171         __raw_writel(addr, fb_data->hwp + SPDC_PRE_BUF);
172 }
173
174 static inline void spdc_set_cntbuf_addr(mxc_spdc_t *fb_data)
175 {
176         u32 addr = fb_data->fresh_param.buf_addr.frm_cnt_buf_phys_addr;
177         __raw_writel(addr, fb_data->hwp + SPDC_CNT_BUF);
178 }
179
180 static inline void spdc_set_lutbuf_addr(mxc_spdc_t *fb_data)
181 {
182         u32 addr = fb_data->fresh_param.buf_addr.lut_buf_phys_addr;
183         __raw_writel(addr, fb_data->hwp + SPDC_LUT_BUF);
184 }
185
186 static inline void spdc_set_update_coord(mxc_spdc_t *fb_data)
187 {
188         u32 x = fb_data->fresh_param.update_region.left;
189         u32 y = fb_data->fresh_param.update_region.top;
190
191         if (!x)
192                 x++;
193         if (!y)
194                 y++;
195
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);
200 }
201
202 static inline void spdc_set_update_dimensions(mxc_spdc_t *fb_data)
203 {
204         u32 w = fb_data->fresh_param.update_region.width;
205         u32 h = fb_data->fresh_param.update_region.height;
206
207         if (!w)
208                 w++;
209         if (!h)
210                 h++;
211
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);
216 }
217
218 static inline void spdc_set_update_temper(mxc_spdc_t *fb_data)
219 {
220         s8 temper = (s8)(fb_data->fresh_param.temper & 0xFF) << 1;
221
222         if (temper > -110 && temper < 200)
223                 __raw_writel(temper, fb_data->hwp + SPDC_TEMP_INFO);
224         else
225                 __raw_writel(SPDC_DEFAULT_TEMP, fb_data->hwp + SPDC_TEMP_INFO);
226 }
227
228 static inline void spdc_trigger_update(mxc_spdc_t *fb_data)
229 {
230         u32 val;
231         struct partial_refresh_param *fresh_param = &fb_data->fresh_param;
232
233         if ((fresh_param->wave_mode & SPDC_WAV_MODE_MASK) && fresh_param->flash)
234                 val = SPDC_DISP_TRIGGER_FLASH;
235         else
236                 val = 0;
237
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);
242 }
243
244 static bool is_lut_checksum_ok(mxc_spdc_t *fb_data)
245 {
246         u32 status;
247
248         status = __raw_readl(fb_data->hwp + SPDC_STATUS);
249         status &= SPDC_IRQ_STA_ERR;
250
251         return status ? true : false;
252 }
253
254 static void spdc_clk_gate(mxc_spdc_t *fb_data, bool enable)
255 {
256         if (enable)
257                 __raw_writel(SPDC_SW_GATE_CLK_ENABLE,
258                 fb_data->hwp + SPDC_SW_GATE_CLK);
259         else
260                 __raw_writel(~SPDC_SW_GATE_CLK_ENABLE,
261                 fb_data->hwp + SPDC_SW_GATE_CLK);
262 }
263
264 static int update_panel_init_set(mxc_spdc_t *fb_data)
265 {
266         int ret = 0;
267         u32 init_val;
268
269         get_panel_init_set(&fb_data->panel_set, &init_val);
270         dev_dbg(fb_data->dev, "panel init setting:%x\n", init_val);
271
272         __raw_writel(init_val, fb_data->hwp + SPDC_PANEL_INIT_SET);
273
274         /*wait init setting update finish*/
275         ret = wait_for_completion_timeout(&fb_data->init_finish,
276                                 msecs_to_jiffies(4000));
277         if (!ret)
278                 dev_err(fb_data->dev, "Timed out for init setting!\n");
279
280         return ret;
281 }
282
283 static void spdc_panel_pwr_on(mxc_spdc_t *fb_data)
284 {
285         fb_data->panel_set.power_ready = POWER_READY_ON;
286 }
287
288 static void spdc_panel_pwr_down(mxc_spdc_t *fb_data)
289 {
290         fb_data->panel_set.power_ready = POWER_READY_OFF;
291 }
292
293 static void spdc_powerdown(mxc_spdc_t *fb_data)
294 {
295         mutex_lock(&fb_data->power_mutex);
296
297         /* If powering_down has been cleared, a powerup
298         * request is pre-empting this powerdown request.
299         */
300         if (!fb_data->powering_down
301                 || (fb_data->power_state == POWER_STATE_OFF)) {
302                 mutex_unlock(&fb_data->power_mutex);
303                 return;
304         }
305
306         dev_dbg(fb_data->dev, "spdc Powerdown\n");
307
308         /* Disable power to the AUO panel */
309         regulator_disable(fb_data->vcom_regulator);
310         regulator_disable(fb_data->display_regulator);
311
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);
316
317         /* Disable pins used by SPDC (to prevent leakage current) */
318         if (fb_data->pdata->disable_pins)
319                 fb_data->pdata->disable_pins();
320
321         /* turn off the V3p3 */
322         regulator_disable(fb_data->v3p3_regulator);
323
324         fb_data->power_state = POWER_STATE_OFF;
325         fb_data->powering_down = false;
326         spdc_panel_pwr_down(fb_data);
327
328         if (fb_data->wait_for_powerdown) {
329                 fb_data->wait_for_powerdown = false;
330                 complete(&fb_data->powerdown_compl);
331         }
332
333         mutex_unlock(&fb_data->power_mutex);
334 }
335
336 static void spdc_powerup(mxc_spdc_t *fb_data)
337 {
338         int ret = 0;
339         mutex_lock(&fb_data->power_mutex);
340
341         /*
342          * If power down request is pending, clear
343          * powering_down to cancel the request.
344          */
345         if (fb_data->powering_down)
346                 fb_data->powering_down = false;
347
348         if (fb_data->power_state == POWER_STATE_ON) {
349                 mutex_unlock(&fb_data->power_mutex);
350                 return;
351         }
352
353         dev_dbg(fb_data->dev, "spdc Powerup\n");
354
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);
361                 return;
362         }
363
364         msleep(1);
365
366         /* Enable pins used by SPDC */
367         if (fb_data->pdata->enable_pins)
368                 fb_data->pdata->enable_pins();
369
370         /* Enable clocks to SPDC */
371         clk_enable(fb_data->spdc_clk_axi);
372         clk_enable(fb_data->spdc_clk_pix);
373
374         /*disable spdc gate*/
375         spdc_clk_gate(fb_data, false);
376
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);
383                 return;
384         }
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);
390                 return;
391         }
392
393         fb_data->power_state = POWER_STATE_ON;
394         spdc_panel_pwr_on(fb_data);
395
396         mutex_unlock(&fb_data->power_mutex);
397 }
398
399 #ifdef DEBUG
400 static void
401 check_waveform(u32 *wv_buf_orig, u32 *wv_buf_cur, u32 wv_buf_size)
402 {
403         int i;
404         bool is_mismatch = false;
405         for (i = 0; i < wv_buf_size; i++) {
406                 if (wv_buf_orig[i] != wv_buf_cur[i]) {
407                         is_mismatch = true;
408                         printk(KERN_ERR "Waveform mismatch!\n");
409                 }
410         }
411
412         if (!is_mismatch)
413                 printk(KERN_DEBUG "No mismatches!\n");
414 }
415 #else
416 static void
417 check_waveform(u32 *wv_buf_orig, u32 *wv_buf_cur, u32 wv_buf_size) {}
418 #endif
419
420 static void get_spdc_version(mxc_spdc_t *fb_data)
421 {
422         struct mxc_spdc_version *spdc_ver = &fb_data->spdc_ver;
423         u32 disp_id, tcon_id;
424
425         disp_id = __raw_readl(fb_data->hwp + SPDC_DISP_VER);
426         tcon_id = __raw_readl(fb_data->hwp + SPDC_TCON_VER);
427
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;
432
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);
435 }
436
437 static void spdc_set_update_concurrency(mxc_spdc_t *fb_data)
438 {
439         u32 concur_mode;
440
441         concur_mode = fb_data->fresh_param.concur & 0xFF;
442         concur_mode |= (SPDC_LUT_MODE_OFFSET << 8);
443
444         __raw_writel(concur_mode, fb_data->hwp + SPDC_LUT_PARA_UPDATE);
445 }
446
447 static bool is_preprocess_list_full(mxc_spdc_t *fb_data)
448 {
449         /* Check to see if preprocess are full in this list */
450         if (fb_data->upd_preprocess_num >= SPDC_MAX_NUM_PREPROCESS)
451                 return true;
452         else
453                 return false;
454 }
455
456 static void spdc_submit_update(mxc_spdc_t *fb_data)
457 {
458         fb_data->updates_active = true;
459
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);
465 }
466
467 static int spdc_init_sequence(mxc_spdc_t *fb_data)
468 {
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;
473         u32 xres, yres;
474         int ret = -EFAULT;
475
476         /*init spdc power*/
477         spdc_powerup(fb_data);
478
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);
485
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;
492
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;
498         } else {
499                 xres = screeninfo->xres;
500                 yres = screeninfo->yres;
501         }
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;
506
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;
511
512         spdc_set_update_coord(fb_data);
513         spdc_set_update_dimensions(fb_data);
514
515         spdc_set_update_temper(fb_data);
516
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);
521
522         /* load waveform*/
523         spdc_set_lutbuf_addr(fb_data);
524         ret = wait_for_completion_timeout(&fb_data->lut_down,
525                                         msecs_to_jiffies(4000));
526         if (!ret) {
527                 dev_err(fb_data->dev,
528                         "Timed out for lut!\n");
529                 return ret;
530         }
531
532         /* modify lut to fix DC com fading issue,
533          * and fix mode4 close over push
534          */
535         __raw_writel(0x00003906, fb_data->hwp + SPDC_LUT_PARA_UPDATE);
536         __raw_writel(0x00003300, fb_data->hwp + SPDC_LUT_PARA_UPDATE);
537
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);
547
548         return ret;
549 }
550
551 static u32 mxc_spdc_partial_refresh_low(mxc_spdc_t *fb_data, void *buffer)
552 {
553         u8 *fresh_addr;
554         void *pattern = buffer;
555         struct partial_refresh_param *fresh_param = &fb_data->fresh_param;
556         u32 fresh_size;
557         int ret = 0;
558
559         fb_data->updates_active = true;
560
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);
566
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 *
573                                         fresh_param->stride;
574                         pattern +=  fresh_param->update_region.width;
575                 }
576         }
577
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);
583
584         ret = wait_for_completion_timeout(&fb_data->update_finish,
585                                         msecs_to_jiffies(3000));
586         if (!ret) {
587                 dev_err(fb_data->dev,
588                         "display update timeout!\n");
589                 return -ETIMEDOUT;
590         }
591
592         return ret;
593 }
594
595 static u32 spdc_fb_dev_init(mxc_spdc_t *fb_data)
596 {
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;
601
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;
606
607         fb_data->fresh_param.temper = SPDC_DEFAULT_TEMP;
608
609         return 0;
610 }
611
612 /**
613  * mxc_spdc_device_is_busy - check spdc device busy status.
614  * Returns 0 if spdc device is idle.
615  */
616 static int mxc_spdc_device_is_busy(mxc_spdc_t *fb_data)
617 {
618         u32 status;
619         u32 orig_jiffies = jiffies;
620
621         while (1) {
622                 status = __raw_readl(fb_data->hwp + SPDC_STATUS);
623                 if ((status & SPDC_PANEL_STAUTS_BUSY) &&
624                         ((status & 0xF0) == SPDC_TCON_STATUS_IDLE))
625                         break;
626
627                 if (signal_pending(current)) {
628                         dev_dbg(fb_data->dev, "SPDC Interrupted\n");
629                         return -EINTR;
630                 }
631
632                 if (time_after(jiffies, orig_jiffies +
633                                 msecs_to_jiffies(3000))) {
634                         dev_dbg(fb_data->dev, "SPDC is busy\n");
635                          return -ETIMEDOUT;
636                 }
637
638                 schedule();
639         }
640
641         return 0;
642 }
643
644 static bool is_free_list_full(mxc_spdc_t *fb_data)
645 {
646         int count = 0;
647         struct update_data_list *plist;
648
649         /* Count buffers in free buffer list */
650         list_for_each_entry(plist, &fb_data->upd_buf_free_list, list)
651                 count++;
652
653         /* Check to see if all buffers are in this list */
654         if (count == fb_data->max_num_updates)
655                 return true;
656         else
657                 return false;
658 }
659
660 static void spdc_draw_mode0(mxc_spdc_t *fb_data)
661 {
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;
665         u32 xres, yres;
666         int ret;
667
668         fb_data->fresh_param.buf_addr.next_buf_phys_addr =
669                 fb_data->phys_start;
670
671         fb_data->hw_ready = true;
672         fb_data->hw_initializing = false;
673
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;
679         } else {
680                 xres = screeninfo->xres;
681                 yres = screeninfo->yres;
682         }
683
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;
692         update.flags = 0;
693
694         upd_marker_data.update_marker = update.update_marker;
695
696         mxc_spdc_fb_send_update(&update, &fb_data->info);
697
698         /* Block on initial update */
699         ret = mxc_spdc_fb_wait_update_complete(&upd_marker_data,
700                 &fb_data->info);
701         if (ret < 0)
702                 dev_err(fb_data->dev,
703                 "Wait for update complete failed, Err:%d", ret);
704 }
705
706 static void
707 spdc_fb_fw_handler(const struct firmware *fw, void *context)
708 {
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;
713         u8 *wv_file;
714         int ret;
715
716         if (fw == NULL) {
717                 /* If default FW file load failed, we give up */
718                 if (fb_data->fw_default_load)
719                         return;
720
721                 /* Try to load default waveform */
722                 fb_data->fw_default_load = true;
723
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);
727                 if (ret) {
728                         dev_err(fb_data->dev,
729                         "Failed to load waveform image with err %d\n", ret);
730                         return;
731                 }
732         }
733
734         wv_file = (u8 *)fw->data;
735         memcpy(fb_data->virt_lut_buf, wv_file, fw->size);
736
737         check_waveform((u32 *)wv_file, (u32 *)fb_data->virt_lut_buf,
738                                         fw->size / 4);
739         release_firmware(fw);
740
741         /* Enable clocks to access SPDC regs */
742         clk_enable(fb_data->spdc_clk_axi);
743
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);
748
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);
755
756                 spdc_pix_rate = target_pix_clk;
757                 while (spdc_pix_rate < rounded_parent_rate)
758                         spdc_pix_rate *= 2;
759                 clk_set_rate(spdc_parent, spdc_pix_rate);
760
761                 rounded_pix_clk =
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,
769                                 rounded_pix_clk);
770         }
771
772         clk_set_rate(fb_data->spdc_clk_pix, rounded_pix_clk);
773
774         if (!spdc_init_sequence(fb_data))
775                 return;
776
777         /* display log on picture */
778         spdc_draw_mode0(fb_data);
779 }
780
781
782 static int spdc_fb_init_hw(struct fb_info *info)
783 {
784         mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
785         int ret;
786
787         fb_data->fw_default_load = false;
788         /*
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"
791          */
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");
797         } else
798                 strcat(fb_data->fw_str, "imx/spdc_pvi.fw");
799
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);
803         if (ret) {
804                 dev_err(fb_data->dev,
805                         "Failed to load waveform image with err %d\n", ret);
806                 return ret;
807         }
808
809         return ret;
810 }
811
812 static int mxc_spdc_partial_refresh(mxc_spdc_t *fb_data, void *buffer)
813 {
814         int ret = 0;
815         struct partial_refresh_param *fresh_param = &fb_data->fresh_param;
816
817         if (!fb_data->panel_set.power_ready)
818                 spdc_powerup(fb_data);
819
820         if (!fresh_param->blocking) {
821                 if (mxc_spdc_device_is_busy(fb_data)) {
822                         dev_err(fb_data->dev, "spdc busy!\n");
823                         return (u32) -1;
824                 }
825         } else {
826                 while (mxc_spdc_device_is_busy(fb_data)) {
827                         dev_err(fb_data->dev, "Waiting for spdc idle..\n");
828                         msleep(500);
829                 }
830         }
831
832         ret = mxc_spdc_partial_refresh_low(fb_data, buffer);
833
834         return ret;
835 }
836
837 static int mxc_operaton_update(mxc_spdc_t *fb_data)
838 {
839         int ret = 0;
840         struct partial_refresh_param *fresh_param = &fb_data->fresh_param;
841         u32 operation_mode = fb_data->operation_mode;
842
843         if (!fb_data->panel_set.power_ready)
844                 spdc_powerup(fb_data);
845
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");
850                                 return (u32) -1;
851                         }
852                 } else {
853                         while (mxc_spdc_device_is_busy(fb_data)) {
854                                 dev_err(fb_data->dev, "Waiting spdc idle...\n");
855                                 msleep(500);
856                         }
857                 }
858         } else
859                 operation_mode = SPDC_SW_TCON_RESET_SET;
860
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);
865
866         if (operation_mode == SPDC_SW_TCON_RESET_SET) {
867                 dev_dbg(fb_data->dev, "reinit hw\n");
868                 mdelay(500);
869
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");
875         }
876
877         return ret;
878 }
879
880 static int mxc_spdc_refresh_display(mxc_spdc_t *fb_data)
881 {
882         struct partial_refresh_param *fresh_param = &fb_data->fresh_param;
883         u32 operation_mode = fb_data->operation_mode;
884         int ret = 0;
885
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;
892
893         if (operation_mode && operation_mode < SPDC_FULL_REFRESH)
894                 ret = mxc_operaton_update(fb_data);
895         else
896                 ret = mxc_spdc_partial_refresh(fb_data, NULL);
897
898         return ret;
899 }
900
901 static void mxc_spdc_find_match_mode(mxc_spdc_t *fb_data)
902 {
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;
906         u32 i = 0;
907         u32 j = 0;
908         u32 default_mode = 0xFF;
909
910         if (fb_data->panel_set.rgbw_mode_enable)
911                 spdc_res_map = &spdc_rgbw_res_map[0];
912         else
913                 spdc_res_map = &spdc_gray_res_map[0];
914
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;
921                                 default_mode = i;
922                                 break;
923                         }
924                         j++;
925                 }
926
927                 if (default_mode != 0xFF)
928                         break;
929                 j = 0;
930                 i++;
931                 spdc_mode = &fb_data->pdata->spdc_mode[i];
932         }
933
934         fb_data->cur_mode = spdc_mode;
935 }
936
937 static int mxc_spdc_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
938 {
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;
943
944         if (offset + size > info->fix.smem_len)
945                 return -EINVAL;
946
947         pos = (unsigned long)info->fix.smem_start + offset;
948
949         /* make buffers bufferable */
950         vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
951         vma->vm_flags |= VM_RESERVED | VM_IO;
952
953         while (size > 0) {
954                 page = pos;
955                 if (io_remap_pfn_range(vma, start, page >> PAGE_SHIFT,
956                                         PAGE_SIZE, vma->vm_page_prot))
957                         return -EAGAIN;
958
959                 start += PAGE_SIZE;
960                 pos += PAGE_SIZE;
961                 if (size > PAGE_SIZE)
962                         size -= PAGE_SIZE;
963                 else
964                         size = 0;
965         }
966
967         return 0;
968 }
969
970 static inline u_int _chan_to_field(u_int chan, struct fb_bitfield *bf)
971 {
972         chan &= 0xffff;
973         chan >>= 16 - bf->length;
974         return chan << bf->offset;
975 }
976
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)
979 {
980         if (regno >= 256) /* no. of hw registers */
981                 return 1;
982
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;
987         }
988
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);
997                 break;
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);
1004                 break;
1005         }
1006 #undef CNVT_TOHW
1007         /* Truecolor has hardware independent palette */
1008         if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1009                 if (regno >= 16)
1010                         return 1;
1011
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);
1017         }
1018
1019         return 0;
1020 }
1021
1022 void mxc_spdc_fb_flush_updates(mxc_spdc_t *fb_data)
1023 {
1024         int ret;
1025
1026         /* Grab queue lock to prevent any new updates from being submitted */
1027         mutex_lock(&fb_data->queue_mutex);
1028
1029         /*
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.
1035          */
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;
1042
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));
1047                 if (!ret)
1048                         dev_err(fb_data->dev,
1049                                 "Flush updates timeout! ret = 0x%x\n", ret);
1050
1051                 mutex_lock(&fb_data->queue_mutex);
1052                 fb_data->waiting_for_idle = false;
1053         }
1054
1055         mutex_unlock(&fb_data->queue_mutex);
1056 }
1057
1058 static int mxc_spdc_fb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
1059 {
1060         int count, index, r;
1061         u16 *red, *green, *blue, *transp;
1062         u16 trans = 0xffff;
1063         mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
1064         int i;
1065
1066         dev_dbg(fb_data->dev, "setcmap\n");
1067
1068         if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) {
1069                 /* Only support an 8-bit, 256 entry lookup */
1070                 if (cmap->len != 256)
1071                         return 1;
1072
1073                 mxc_spdc_fb_flush_updates(fb_data);
1074
1075                 mutex_lock(&fb_data->pxp_mutex);
1076                 /*
1077                  * Store colormap in pxp_conf structure for later transmit
1078                  * to PxP during update process to convert gray pixels.
1079                  *
1080                  * Since red=blue=green for pseudocolor visuals, we can
1081                  * just use red values.
1082                  */
1083                 for (i = 0; i < 256; i++)
1084                         fb_data->pxp_conf.proc_data.lut_map[i] =
1085                                         cmap->red[i] & 0xFF;
1086
1087                 fb_data->pxp_conf.proc_data.lut_map_updated = true;
1088
1089                 mutex_unlock(&fb_data->pxp_mutex);
1090         } else {
1091                 red = cmap->red;
1092                 green   = cmap->green;
1093                 blue    = cmap->blue;
1094                 transp  = cmap->transp;
1095                 index   = cmap->start;
1096
1097                 for (count = 0; count < cmap->len; count++) {
1098                         if (transp)
1099                                 trans = *transp++;
1100                         r = mxc_spdc_fb_setcolreg(index++, *red++,
1101                                 *green++, *blue++, trans, info);
1102                         if (r != 0)
1103                                 return r;
1104                 }
1105         }
1106
1107         return 0;
1108 }
1109
1110 static void adjust_coordinates(u32 xres, u32 yres, u32 rotation,
1111         struct mxcfb_rect *update_region, struct mxcfb_rect *adj_update_region)
1112 {
1113         u32 temp;
1114
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)
1118                 switch (rotation) {
1119                 case FB_ROTATE_UR:
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;
1124                         break;
1125                 case FB_ROTATE_CW:
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;
1131                         break;
1132                 case FB_ROTATE_UD:
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);
1139                         break;
1140                 case FB_ROTATE_CCW:
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;
1146                         break;
1147                 }
1148         else
1149                 switch (rotation) {
1150                 case FB_ROTATE_UR:
1151                         /* No adjustment needed */
1152                         break;
1153                 case FB_ROTATE_CW:
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;
1161                         break;
1162                 case FB_ROTATE_UD:
1163                         update_region->top = yres -
1164                                 (update_region->top + update_region->height);
1165                         update_region->left = xres -
1166                                 (update_region->left + update_region->width);
1167                         break;
1168                 case FB_ROTATE_CCW:
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;
1176                         break;
1177                 }
1178 }
1179
1180 static int mxc_spdc_fb_set_fix(struct fb_info *info)
1181 {
1182         struct fb_fix_screeninfo *fix = &info->fix;
1183         struct fb_var_screeninfo *var = &info->var;
1184
1185         fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
1186
1187         fix->type = FB_TYPE_PACKED_PIXELS;
1188         fix->accel = FB_ACCEL_NONE;
1189         if (var->grayscale)
1190                 fix->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
1191         else
1192                 fix->visual = FB_VISUAL_TRUECOLOR;
1193                 fix->xpanstep = 1;
1194         fix->ypanstep = 1;
1195
1196         return 0;
1197 }
1198
1199 static int mxc_spdc_fb_set_par(struct fb_info *info)
1200 {
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;
1206         int i, ret;
1207         __u32 xoffset_old, yoffset_old;
1208
1209         /*
1210          * Can't change the FB parameters until current updates have completed.
1211          * This function returns when all active updates are done.
1212          */
1213         mxc_spdc_fb_flush_updates(fb_data);
1214
1215         mutex_lock(&fb_data->queue_mutex);
1216         /*
1217          * Set all screeninfo except for xoffset/yoffset
1218          * Subsequent call to pan_display will handle those.
1219          */
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);
1226
1227         mutex_lock(&fb_data->pxp_mutex);
1228
1229         /*
1230          * Update PxP config data (used to process FB regions for updates)
1231          * based on FB info and processing tasks required
1232          */
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;
1245
1246         /*
1247          * configure S0 channel parameters
1248          * Parameters should match FB format/width/height
1249          */
1250         if (screeninfo->grayscale)
1251                 pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_GY04;
1252         else {
1253                 switch (screeninfo->bits_per_pixel) {
1254                 case 16:
1255                         pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB565;
1256                         break;
1257                 case 24:
1258                         pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB24;
1259                         break;
1260                 case 32:
1261                         pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB32;
1262                         break;
1263                 default:
1264                         pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB565;
1265                         break;
1266                 }
1267         }
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;
1272
1273         /*
1274          * Initialize Output channel parameters
1275          * Output is Y-only greyscale
1276          * Output width/height will vary based on update region size
1277          */
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;
1281
1282         mutex_unlock(&fb_data->pxp_mutex);
1283
1284         /* active new config, If HW not yet initialized,
1285          * check to see if we are being sent
1286          * an initialization request.
1287          */
1288         if (!fb_data->hw_ready) {
1289                 struct fb_videomode mode;
1290                 bool found_match = false;
1291                 u32 xres_temp;
1292
1293                 fb_var_to_videomode(&mode, screeninfo);
1294
1295                 /* When comparing requested fb mode,
1296                  * we need to use unrotated dimensions
1297                  */
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;
1303                 }
1304
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))
1308                                 continue;
1309                         fb_data->cur_mode = &spdc_modes[i];
1310                         found_match = true;
1311                         break;
1312                 }
1313
1314                 if (!found_match) {
1315                         dev_err(fb_data->dev,
1316                                 "Failed to match requested video mode\n");
1317                         return EINVAL;
1318                 }
1319
1320                 /* Initialize SPDC settings and init panel */
1321                 ret =
1322                 spdc_fb_init_hw((struct fb_info *)fb_data);
1323                 if (ret) {
1324                         dev_err(fb_data->dev,
1325                                 "Failed to load panel waveform data\n");
1326                         return ret;
1327                 }
1328         }
1329
1330         mxc_spdc_fb_set_fix(info);
1331
1332         return 0;
1333 }
1334
1335 static int
1336 mxc_spdc_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1337 {
1338         mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
1339
1340         if (!var->xres)
1341                 var->xres = 1;
1342         if (!var->yres)
1343                 var->yres = 1;
1344
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;
1349
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;
1354
1355         switch (var->bits_per_pixel) {
1356         case 4:
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;
1363                 break;
1364         case 8:
1365                 if (var->grayscale != 0) {
1366                         var->red.length = 8;
1367                         var->red.offset = 0;
1368                         var->red.msb_right = 0;
1369
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;
1375                 } else {
1376                         var->red.length = 3;
1377                         var->red.offset = 5;
1378                         var->red.msb_right = 0;
1379
1380                         var->green.length = 3;
1381                         var->green.offset = 2;
1382                         var->green.msb_right = 0;
1383
1384                         var->blue.length = 2;
1385                         var->blue.offset = 0;
1386                         var->blue.msb_right = 0;
1387
1388                         var->transp.length = 0;
1389                         var->transp.offset = 0;
1390                         var->transp.msb_right = 0;
1391                 }
1392                 break;
1393         case 16:
1394                 var->red.length = 5;
1395                 var->red.offset = 11;
1396                 var->red.msb_right = 0;
1397
1398                 var->green.length = 6;
1399                 var->green.offset = 5;
1400                 var->green.msb_right = 0;
1401
1402                 var->blue.length = 5;
1403                 var->blue.offset = 0;
1404                 var->blue.msb_right = 0;
1405
1406                 var->transp.length = 0;
1407                 var->transp.offset = 0;
1408                 var->transp.msb_right = 0;
1409                 break;
1410         case 24:
1411                 var->red.length = 8;
1412                 var->red.offset = 16;
1413                 var->red.msb_right = 0;
1414
1415                 var->green.length = 8;
1416                 var->green.offset = 8;
1417                 var->green.msb_right = 0;
1418
1419                 var->blue.length = 8;
1420                 var->blue.offset = 0;
1421                 var->blue.msb_right = 0;
1422
1423                 var->transp.length = 0;
1424                 var->transp.offset = 0;
1425                 var->transp.msb_right = 0;
1426                 break;
1427         case 32:
1428                 var->red.length = 8;
1429                 var->red.offset = 16;
1430                 var->red.msb_right = 0;
1431
1432                 var->green.length = 8;
1433                 var->green.offset = 8;
1434                 var->green.msb_right = 0;
1435
1436                 var->blue.length = 8;
1437                 var->blue.offset = 0;
1438                 var->blue.msb_right = 0;
1439
1440                 var->transp.length = 8;
1441                 var->transp.offset = 24;
1442                 var->transp.msb_right = 0;
1443                 break;
1444         }
1445
1446         switch (var->rotate) {
1447         case FB_ROTATE_UR:
1448         case FB_ROTATE_UD:
1449                 var->xres = fb_data->native_width;
1450                 var->yres = fb_data->native_height;
1451                 break;
1452         case FB_ROTATE_CW:
1453         case FB_ROTATE_CCW:
1454                 var->xres = fb_data->native_height;
1455                 var->yres = fb_data->native_width;
1456                 break;
1457         default:
1458                 /* Invalid rotation value */
1459                 var->rotate = 0;
1460                 dev_dbg(fb_data->dev, "Invalid rotation request\n");
1461                 return -EINVAL;
1462         }
1463
1464         var->xres_virtual = ALIGN(var->xres, 32);
1465         var->yres_virtual = ALIGN(var->yres, 128) * fb_data->num_screens;
1466
1467         var->height = -1;
1468         var->width = -1;
1469
1470         return 0;
1471 }
1472
1473 void mxc_spdc_fb_set_waveform_modes(struct mxcfb_waveform_modes *modes,
1474         struct fb_info *info)
1475 {
1476         mxc_spdc_t *fb_data = info ?
1477                 (mxc_spdc_t *)info:g_fb_data;
1478
1479         mutex_lock(&fb_data->queue_mutex);
1480
1481         memcpy(&fb_data->wv_modes, modes, sizeof(struct mxcfb_waveform_modes));
1482
1483         mutex_unlock(&fb_data->queue_mutex);
1484 }
1485 EXPORT_SYMBOL(mxc_spdc_fb_set_waveform_modes);
1486
1487 /* To stick with non-fractional degrees for the sake
1488  *  of API consistency with EPDC.
1489  */
1490 int mxc_spdc_fb_set_temperature(int temperature, struct fb_info *info)
1491 {
1492         mxc_spdc_t *fb_data = info ?
1493                 (mxc_spdc_t *)info:g_fb_data;
1494         s8 temper = (s8)(temperature & 0xFF) << 1;
1495
1496         mutex_lock(&fb_data->queue_mutex);
1497
1498         if (temper > -110 && temper < 200)
1499                 __raw_writel(temper, fb_data->hwp + SPDC_TEMP_INFO);
1500         else
1501                 __raw_writel(SPDC_DEFAULT_TEMP, fb_data->hwp + SPDC_TEMP_INFO);
1502
1503         mutex_unlock(&fb_data->queue_mutex);
1504
1505         return 0;
1506 }
1507 EXPORT_SYMBOL(mxc_spdc_fb_set_temperature);
1508
1509
1510 int mxc_spdc_fb_set_auto_update(u32 auto_mode, struct fb_info *info)
1511 {
1512         mxc_spdc_t *fb_data = info ?
1513                 (mxc_spdc_t *)info:g_fb_data;
1514
1515         dev_dbg(fb_data->dev, "Setting auto update mode to %d\n", auto_mode);
1516
1517         if ((auto_mode == AUTO_UPDATE_MODE_AUTOMATIC_MODE)
1518                 || (auto_mode == AUTO_UPDATE_MODE_REGION_MODE))
1519                 fb_data->auto_mode = auto_mode;
1520         else {
1521                 dev_err(fb_data->dev, "Invalid auto update mode parameter.\n");
1522                 return -EINVAL;
1523         }
1524
1525         return 0;
1526 }
1527 EXPORT_SYMBOL(mxc_spdc_fb_set_auto_update);
1528
1529
1530 int mxc_spdc_fb_set_upd_scheme(u32 upd_scheme, struct fb_info *info)
1531 {
1532         mxc_spdc_t *fb_data = info ?
1533                 (mxc_spdc_t *)info:g_fb_data;
1534
1535         dev_dbg(fb_data->dev, "Setting optimization level to %d\n", upd_scheme);
1536
1537         /*
1538          * Can't change the scheme until current updates have completed.
1539          * This function returns when all active updates are done.
1540          */
1541         mxc_spdc_fb_flush_updates(fb_data);
1542
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;
1547         else {
1548                 dev_err(fb_data->dev, "Invalid update scheme specified.\n");
1549                 return -EINVAL;
1550         }
1551
1552         return 0;
1553 }
1554 EXPORT_SYMBOL(mxc_spdc_fb_set_upd_scheme);
1555
1556 /* Callback function triggered after PxP receives an EOF interrupt */
1557 static void pxp_dma_done(void *arg)
1558 {
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;
1563
1564         /* This call will signal wait_for_completion_timeout()
1565          * in send_buffer_to_pxp
1566          */
1567         complete(&fb_data->pxp_tx_cmpl);
1568 }
1569
1570 static bool chan_filter(struct dma_chan *chan, void *arg)
1571 {
1572         if (imx_dma_is_pxp(chan))
1573                 return true;
1574         else
1575                 return false;
1576 }
1577
1578 /* Function to request PXP DMA channel */
1579 static int pxp_chan_init(mxc_spdc_t *fb_data)
1580 {
1581         dma_cap_mask_t mask;
1582         struct dma_chan *chan;
1583
1584         /*
1585          * Request a free channel
1586          */
1587         dma_cap_zero(mask);
1588         dma_cap_set(DMA_SLAVE, mask);
1589         dma_cap_set(DMA_PRIVATE, mask);
1590         chan = dma_request_channel(mask, chan_filter, NULL);
1591         if (!chan) {
1592                 dev_err(fb_data->dev, "Unsuccessfully received channel!!!!\n");
1593                 return -EBUSY;
1594         }
1595
1596         fb_data->pxp_chan = to_pxp_channel(chan);
1597         fb_data->pxp_chan->client = fb_data;
1598
1599         init_completion(&fb_data->pxp_tx_cmpl);
1600
1601         return 0;
1602 }
1603
1604 /*
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.
1608  */
1609 static int pxp_process_update(mxc_spdc_t *fb_data,
1610                           u32 src_width, u32 src_height,
1611                           struct mxcfb_rect *update_region)
1612 {
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;
1620         int i, ret;
1621         int length;
1622
1623         /* First, check to see that we have acquired a PxP Channel object */
1624         if (fb_data->pxp_chan == NULL) {
1625                 /*
1626                  * PxP Channel has not yet been created and initialized,
1627                  * so let's go ahead and try
1628                  */
1629                 ret = pxp_chan_init(fb_data);
1630                 if (ret) {
1631                         /*
1632                          * PxP channel init failed, and we can't use the
1633                          * PxP until the PxP DMA driver has loaded, so we abort
1634                          */
1635                         dev_err(fb_data->dev, "PxP chan init failed\n");
1636                         return -ENODEV;
1637                 }
1638         }
1639
1640         /*
1641          * Init completion, so that we
1642          * can be properly informed of the completion
1643          * of the PxP task when it is done.
1644          */
1645         init_completion(&fb_data->pxp_tx_cmpl);
1646
1647         dma_chan = &fb_data->pxp_chan->dma_chan;
1648
1649         txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg, 2,
1650                                                  DMA_TO_DEVICE,
1651                                                  DMA_PREP_INTERRUPT);
1652         if (!txd) {
1653                 dev_err(fb_data->info.device,
1654                         "Error preparing a DMA transaction descriptor.\n");
1655                 return -EIO;
1656         }
1657
1658         txd->callback_param = txd;
1659         txd->callback = pxp_dma_done;
1660
1661         /*
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.
1665          */
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;
1672
1673         /*
1674          * Because only YUV/YCbCr image can be scaled, configure
1675          * drect equivalent to srect, as such do not perform scaling.
1676          */
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;
1681
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;
1686
1687         pxp_conf->out_param.width = update_region->width;
1688         pxp_conf->out_param.height = update_region->height;
1689
1690         if ((proc_data->rotate == 90) || (proc_data->rotate == 270))
1691                 pxp_conf->out_param.stride = update_region->height;
1692         else
1693                 pxp_conf->out_param.stride = update_region->width;
1694
1695         desc = to_tx_desc(txd);
1696         length = desc->len;
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));
1709                 }
1710                 /* TODO: OverLay */
1711
1712                 desc = desc->next;
1713         }
1714
1715         /* Submitting our TX starts the PxP processing task */
1716         cookie = txd->tx_submit(txd);
1717         if (cookie < 0) {
1718                 dev_err(fb_data->info.device, "Error sending FB through PxP\n");
1719                 return -EIO;
1720         }
1721
1722         fb_data->txd = txd;
1723
1724         /* trigger ePxP */
1725         dma_async_issue_pending(dma_chan);
1726
1727         return 0;
1728 }
1729
1730 static int pxp_complete_update(mxc_spdc_t *fb_data, u32 *hist_stat)
1731 {
1732         int ret;
1733         /*
1734          * Wait for completion event, which will be set
1735          * through our TX callback function.
1736          */
1737         ret = wait_for_completion_timeout(&fb_data->pxp_tx_cmpl, HZ / 10);
1738         if (ret <= 0) {
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;
1745         }
1746
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;
1750
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;
1754
1755         dev_dbg(fb_data->dev, "TX completed\n");
1756
1757         return 0;
1758 }
1759
1760 static void copy_to_next_buffer(mxc_spdc_t *fb_data,
1761         struct update_data_list *upd_data_list)
1762 {
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;
1769         int i;
1770
1771         switch (fb_data->spdc_fb_var.rotate) {
1772         case FB_ROTATE_UR:
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;
1778                 break;
1779         case FB_ROTATE_CW:
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;
1787                 break;
1788         case FB_ROTATE_UD:
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;
1797                 break;
1798         case FB_ROTATE_CCW:
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;
1806                 break;
1807         }
1808
1809         /* pxp output Y4 data.
1810          * Copy the raw data to related region in next buffer.
1811          */
1812         left_offs = adj_update_region.left / 2;
1813         line_width = adj_update_region.width / 2;
1814
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);
1819
1820                 dst_ptr += dst_stride;
1821                 temp_buf_ptr += line_width;
1822         }
1823 }
1824
1825 static int spdc_process_update(struct update_data_list *upd_data_list,
1826                                    mxc_spdc_t *fb_data)
1827 {
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;
1837         u32 hist_stat = 0;
1838         bool use_temp_buf = false;
1839         int ret;
1840
1841         /*
1842          * Are we using FB or an alternate (overlay)
1843          * buffer for source of update?
1844          */
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;
1848                 src_upd_region =
1849                 &upd_desc_list->upd_data.alt_buffer_data.alt_update_region;
1850         } else {
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;
1854         }
1855
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;
1859
1860         bytes_per_pixel = fb_data->spdc_fb_var.bits_per_pixel / 8;
1861
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);
1865
1866         offset_from_4 = src_upd_region->left & 0x3;
1867         input_unaligned = ((offset_from_4 * bytes_per_pixel % 4) != 0) ?
1868                                 true : false;
1869
1870         if (input_unaligned) {
1871                 /* Leave a gap between PxP input addr
1872                  * and update region pixels
1873                  */
1874                 pxp_input_offs =
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
1879                  */
1880                 pxp_upd_region.left = (offset_from_4 * bytes_per_pixel % 4)
1881                                         / bytes_per_pixel;
1882         } else {
1883                 pxp_input_offs =
1884                         (src_upd_region->top * src_width + src_upd_region->left)
1885                         * bytes_per_pixel;
1886                 pxp_upd_region.left = 0;
1887         }
1888         pxp_upd_region.top = 0;
1889
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);
1894         } else {
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);
1898         }
1899
1900         switch (fb_data->spdc_fb_var.rotate) {
1901         case FB_ROTATE_UR:
1902         default:
1903                 post_rotation_xcoord = pxp_upd_region.left;
1904                 post_rotation_ycoord = pxp_upd_region.top;
1905                 width_pxp_blocks = pxp_upd_region.width;
1906                 break;
1907         case FB_ROTATE_CW:
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;
1912                 break;
1913         case FB_ROTATE_UD:
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;
1919                 break;
1920         case FB_ROTATE_CCW:
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;
1925                 break;
1926         }
1927
1928         /* Update region start coord to force PxP to
1929          * process full 8x8 regions
1930          */
1931         pxp_upd_region.top &= ~0x7;
1932         pxp_upd_region.left &= ~0x7;
1933
1934         pxp_output_shift = ALIGN(post_rotation_xcoord, 8)
1935                 - post_rotation_xcoord;
1936         pxp_output_offs = post_rotation_ycoord * width_pxp_blocks
1937                 + pxp_output_shift;
1938         upd_desc_list->spdc_offs = ALIGN(pxp_output_offs, 8);
1939
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
1945                                 + pxp_input_offs;
1946         else {
1947                 sg_dma_address(&fb_data->sg[0]) =
1948                         fb_data->info.fix.smem_start + fb_data->fb_offset
1949                         + pxp_input_offs;
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));
1954         }
1955
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));
1963         } else {
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));
1969         }
1970
1971         /*
1972          * Set PxP LUT transform type based on update flags.
1973          */
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 |=
1982                         PXP_LUT_USE_CMAP;
1983
1984         /*
1985          * Toggle inversion processing if 8-bit
1986          * inverted is the current pixel format.
1987          */
1988         if (fb_data->spdc_fb_var.grayscale == GRAYSCALE_4BIT_INVERTED)
1989                 fb_data->pxp_conf.proc_data.lut_transform ^= PXP_LUT_INVERT;
1990
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,
1993                 &pxp_upd_region);
1994         if (ret) {
1995                 dev_err(fb_data->dev, "Unable to submit PxP update task.\n");
1996                 mutex_unlock(&fb_data->pxp_mutex);
1997                 return ret;
1998         }
1999
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);
2004         }
2005
2006         /* This is a blocking call, so upon return PxP tx should be done */
2007         ret = pxp_complete_update(fb_data, &hist_stat);
2008         if (ret) {
2009                 dev_err(fb_data->dev, "Unable to complete PxP update task.\n");
2010                 mutex_unlock(&fb_data->pxp_mutex);
2011                 return ret;
2012         }
2013
2014         if (use_temp_buf)
2015                 copy_to_next_buffer(fb_data, upd_data_list);
2016
2017         mutex_unlock(&fb_data->pxp_mutex);
2018
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;
2033                 else
2034                         upd_desc_list->upd_data.waveform_mode =
2035                                 fb_data->wv_modes.mode_gc32;
2036
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);
2039         }
2040
2041         return 0;
2042 }
2043
2044 static bool spdc_submit_concur(mxc_spdc_t *fb_data,
2045                         struct update_desc_list *update_to_concur)
2046 {
2047         struct mxcfb_update_data *a, *b;
2048         struct mxcfb_rect *arect, *brect;
2049         struct update_data_list *next_upd;
2050         int i = 0;
2051
2052         a = &update_to_concur->upd_data;
2053         arect = &update_to_concur->upd_data.update_region;
2054
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;
2059
2060                 /* Updates with different waveform
2061                  * must be executed sequentially.
2062                  */
2063                 if (a->waveform_mode != b->waveform_mode)
2064                         break;
2065
2066                 /*
2067                   * Concurrency update must has no overlay
2068                   */
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)))
2073                         break;
2074
2075                 i++;
2076         }
2077
2078         if (i != fb_data->upd_preprocess_num)
2079                 return false;
2080
2081         return true;
2082 }
2083
2084 static int spdc_submit_merge(struct update_desc_list *upd_desc_list,
2085                                 struct update_desc_list *update_to_merge)
2086 {
2087         struct mxcfb_update_data *a, *b;
2088         struct mxcfb_rect *arect, *brect;
2089         struct mxcfb_rect combine;
2090         bool use_flags = false;
2091
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;
2096
2097         /*
2098          * Updates with different flags must be executed sequentially.
2099          * Halt the merge process to ensure this.
2100          */
2101         if (a->flags != b->flags) {
2102                 /*
2103                  * Special exception: if update regions are identical,
2104                  * we may be able to merge them.
2105                  */
2106                 if ((arect->left != brect->left) ||
2107                         (arect->top != brect->top) ||
2108                         (arect->width != brect->width) ||
2109                         (arect->height != brect->height))
2110                         return MERGE_BLOCK;
2111
2112                 use_flags = true;
2113         }
2114
2115         if (a->waveform_mode != b->waveform_mode)
2116                 a->waveform_mode = WAVEFORM_MODE_AUTO;
2117
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))
2122                 return MERGE_FAIL;
2123
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);
2134
2135         *arect = combine;
2136
2137         /* Use flags of the later update */
2138         if (use_flags)
2139                 a->flags = b->flags;
2140
2141         /* Merge markers */
2142         list_splice_tail(&update_to_merge->upd_marker_list,
2143                 &upd_desc_list->upd_marker_list);
2144
2145         return MERGE_OK;
2146
2147 }
2148
2149 static void spdc_submit_work_func(struct work_struct *work)
2150 {
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;
2158         bool is_transform;
2159         u32 update_addr;
2160
2161         /* Protect access to buffer queues and to update HW */
2162         mutex_lock(&fb_data->queue_mutex);
2163
2164         /* get a buffer from free list */
2165         if (list_empty(&fb_data->upd_buf_free_list)) {
2166                 mutex_unlock(&fb_data->queue_mutex);
2167                 return;
2168         }
2169
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) {
2173
2174                         current_marker =
2175                         list_entry((&next_desc->upd_marker_list)->next,
2176                                 struct update_marker_data, upd_list);
2177
2178                         if (current_marker->update_marker) {
2179                                 fb_data->submit_upd_sta = 0;
2180                                 break;
2181                         }
2182
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");
2187                                 break;
2188                         }
2189
2190                         upd_data_list =
2191                         list_entry(fb_data->upd_buf_free_list.next,
2192                                 struct update_data_list, list);
2193                         upd_data_list->update_desc = next_desc;
2194
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,
2200                                                 next_desc)) {
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 =
2206                                                         SPDC_CONCUR_UPD;
2207                                 } else
2208                                         break;
2209                         } else
2210                                 break;
2211
2212                         /* submit to pxp process */
2213                         list_del_init(&upd_data_list->list);
2214                         goto pxp_process;
2215                 }
2216
2217                 upd_data_list = NULL;
2218                 if (fb_data->submit_upd_sta == SPDC_CONCUR_UPD)
2219                         fb_data->submit_upd_sta |= SPDC_QUEUE_UPD;
2220                 else
2221                         fb_data->submit_upd_sta = SPDC_QUEUE_UPD;
2222         }
2223
2224         list_for_each_entry_safe(next_desc, temp_desc,
2225                         &fb_data->upd_pending_list, list) {
2226
2227                 if (!upd_data_list) {
2228
2229                         if (list_empty(&fb_data->upd_buf_free_list)) {
2230                                 dev_dbg(fb_data->dev,
2231                                         "buf_free_list is empty\n");
2232                                 break;
2233                         }
2234                         upd_data_list =
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);
2240
2241                         if (fb_data->upd_scheme == UPDATE_SCHEME_QUEUE)
2242                                 break;
2243                 } else {
2244                         switch (spdc_submit_merge(upd_data_list->update_desc,
2245                                         next_desc)) {
2246                         case MERGE_OK:
2247                                 dev_dbg(fb_data->dev,
2248                                         "Update merged [queue]\n");
2249                                 list_del_init(&next_desc->list);
2250                                 kfree(next_desc);
2251                                 break;
2252                         case MERGE_FAIL:
2253                                 dev_dbg(fb_data->dev,
2254                                         "Update not merged [queue]\n");
2255                                 break;
2256                         case MERGE_BLOCK:
2257                                 dev_dbg(fb_data->dev,
2258                                         "Merge blocked [collision]\n");
2259                                 end_merge = true;
2260                                 break;
2261                         }
2262
2263                         if (end_merge)
2264                                 break;
2265                 }
2266         }
2267
2268         /* Is update list empty? */
2269         if (!upd_data_list) {
2270                 mutex_unlock(&fb_data->queue_mutex);
2271                 return;
2272         }
2273
2274 pxp_process:
2275         /*
2276          * If no processing required, skip update processing
2277          * No processing means:
2278          *   - FB unrotated
2279          *   - FB pixel format = 4-bit grayscale
2280          *   - No look-up transformations (inversion, posterization, etc.)
2281          */
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) ?
2285                 true : false;
2286         if ((fb_data->spdc_fb_var.rotate == FB_ROTATE_UR) &&
2287                 (fb_data->spdc_fb_var.grayscale == GRAYSCALE_4BIT) &&
2288                 !is_transform) {
2289
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);
2294
2295                 /*
2296                  * Set update buffer pointer to the start of
2297                  * the update region in the frame buffer.
2298                  */
2299                 upd_region =
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;
2304         } else {
2305
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);
2316
2317                 /* Release buffer queues */
2318                 mutex_unlock(&fb_data->queue_mutex);
2319
2320                 /* Perform PXP processing - SPDC power will also be enabled */
2321                 if (spdc_process_update(upd_data_list, fb_data)) {
2322
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;
2329
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);
2335                         return;
2336                 }
2337
2338                 /* Protect access to buffer queues and to update HW */
2339                 mutex_lock(&fb_data->queue_mutex);
2340
2341                 /* output Y4 format */
2342                 update_addr = upd_data_list->phys_addr +
2343                         + (upd_data_list->update_desc->spdc_offs / 2);
2344         }
2345
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);
2351
2352         /*
2353          * Is the working buffer idle?
2354          * If the working buffer is busy, we must wait for the resource
2355          * to become free.
2356          */
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);
2361
2362                 fb_data->waiting_for_wb = true;
2363
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);
2368         }
2369
2370         if (fb_data->submit_upd_sta != SPDC_CONCUR_UPD)
2371                 fb_data->cur_update = upd_data_list;
2372
2373         /* program SPDC register and trigger to process buffer*/
2374         fb_data->fresh_param.buf_addr.next_buf_phys_addr = update_addr;
2375
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;
2383
2384         spdc_submit_update(fb_data);
2385
2386         /* Release buffer queues */
2387         mutex_unlock(&fb_data->queue_mutex);
2388 }
2389
2390 int mxc_spdc_fb_send_update(struct mxcfb_update_data *upd_data,
2391                                    struct fb_info *info)
2392 {
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;
2399         int ret;
2400
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");
2407                 return -EPERM;
2408         }
2409
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);
2416                 return -EINVAL;
2417         }
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");
2425                 return -EINVAL;
2426         }
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");
2435                         return -EINVAL;
2436                 }
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");
2445                         return -EINVAL;
2446                 }
2447         }
2448
2449         mutex_lock(&fb_data->queue_mutex);
2450
2451         /*
2452          * If we are waiting to go into suspend, or the FB is blanked,
2453          * we do not accept new updates
2454          */
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);
2459                 return -EPERM;
2460         }
2461
2462         if (fb_data->upd_scheme == UPDATE_SCHEME_SNAPSHOT) {
2463                 int count = 0;
2464                 struct update_data_list *plist;
2465
2466                 /* Count buffers in free buffer list */
2467                 list_for_each_entry(plist, &fb_data->upd_buf_free_list, list)
2468                         count++;
2469
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);
2477                         return -ENOMEM;
2478                 }
2479
2480                 /* Grab first available buffer and delete from the free list */
2481                 upd_data_list =
2482                 list_entry(fb_data->upd_buf_free_list.next,
2483                            struct update_data_list, list);
2484
2485                 list_del_init(&upd_data_list->list);
2486         }
2487
2488         /*
2489          * Create new update data structure, fill it with new update
2490          * data and add it to the list of pending updates
2491          */
2492         upd_desc = kzalloc(sizeof(struct update_desc_list), GFP_KERNEL);
2493         if (!upd_desc) {
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);
2499                 }
2500                 mutex_unlock(&fb_data->queue_mutex);
2501                 return -EPERM;
2502         }
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);
2507
2508         /* If marker specified, associate it with a completion */
2509         if (upd_data->update_marker != 0) {
2510
2511                 /* Allocate new update marker and set it up */
2512                 marker_data = kzalloc(sizeof(struct update_marker_data),
2513                                 GFP_KERNEL);
2514                 if (!marker_data) {
2515                         dev_err(fb_data->dev, "No memory for marker!\n");
2516                         mutex_unlock(&fb_data->queue_mutex);
2517                         return -ENOMEM;
2518                 }
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);
2523
2524                 /* Add marker to master marker list */
2525                 list_add_tail(&marker_data->full_list,
2526                         &fb_data->full_marker_list);
2527         }
2528
2529         if (fb_data->upd_scheme != UPDATE_SCHEME_SNAPSHOT) {
2530                 /* Queued update scheme processing */
2531
2532                 mutex_unlock(&fb_data->queue_mutex);
2533
2534                 /* Signal workqueue to handle new update */
2535                 queue_work(fb_data->spdc_submit_workqueue,
2536                         &fb_data->spdc_submit_work);
2537
2538                 return 0;
2539         }
2540
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);
2544
2545         mutex_unlock(&fb_data->queue_mutex);
2546
2547         /*
2548          * Hold on to original screen update region, which we
2549          * will ultimately use when telling SPDC where to update on panel
2550          */
2551         screen_upd_region = &upd_desc->upd_data.update_region;
2552
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;
2561
2562         ret = spdc_process_update(upd_data_list, fb_data);
2563         if (ret) {
2564                 mutex_unlock(&fb_data->pxp_mutex);
2565                 return ret;
2566         }
2567
2568         /* Pass selected waveform mode back to user */
2569         upd_data->waveform_mode = upd_desc->upd_data.waveform_mode;
2570
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);
2575
2576         /* Grab lock for queue manipulation and update submission */
2577         mutex_lock(&fb_data->queue_mutex);
2578
2579         /*
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
2583          */
2584         if (fb_data->cur_update != NULL) {
2585
2586                 /* Add processed Y buffer to update list */
2587                 list_add_tail(&upd_data_list->list, &fb_data->upd_buf_queue);
2588
2589                 /* Return and allow the update to be submitted by the ISR. */
2590                 mutex_unlock(&fb_data->queue_mutex);
2591                 return 0;
2592         }
2593
2594         /* Save current update */
2595         fb_data->cur_update = upd_data_list;
2596
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);
2600
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);
2608
2609         mutex_unlock(&fb_data->queue_mutex);
2610         return 0;
2611 }
2612 EXPORT_SYMBOL(mxc_spdc_fb_send_update);
2613
2614 /*
2615  * return 0 : spdc update is update
2616  */
2617 int
2618 mxc_spdc_fb_wait_update_complete(struct mxcfb_update_marker_data *marker_data,
2619                                 struct fb_info *info)
2620 {
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;
2626         int ret = 0;
2627
2628         /* 0 is an invalid update_marker value */
2629         if (marker_data->update_marker == 0)
2630                 return -EINVAL;
2631
2632         /*
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.
2636          */
2637
2638         /* Grab queue lock to protect access to marker list */
2639         mutex_lock(&fb_data->queue_mutex);
2640
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;
2648                         break;
2649                 }
2650         }
2651
2652         mutex_unlock(&fb_data->queue_mutex);
2653
2654         /*
2655          * If marker not found, it has either been signalled already
2656          * or the update request failed.  In either case, just return.
2657          */
2658         if (!marker_found)
2659                 return ret;
2660
2661         ret = wait_for_completion_timeout(&next_marker->update_completion,
2662                                                 msecs_to_jiffies(8000));
2663         if (!ret) {
2664                 dev_err(fb_data->dev,
2665                         "Timed out waiting for update completion\n");
2666                 return -ETIMEDOUT;
2667         }
2668
2669         /** since SPDC don't support auto collision detect,
2670          *  there alway returns no collision
2671          */
2672         marker_data->collision_test = false;
2673
2674         /* Free update marker object */
2675         kfree(next_marker);
2676
2677         return ret;
2678 }
2679 EXPORT_SYMBOL(mxc_spdc_fb_wait_update_complete);
2680
2681 int mxc_spdc_fb_set_pwrdown_delay(u32 pwrdown_delay,
2682                                 struct fb_info *info)
2683 {
2684         mxc_spdc_t *fb_data = info ?
2685                 (mxc_spdc_t *)info:g_fb_data;
2686
2687         fb_data->pwrdown_delay = pwrdown_delay;
2688
2689         return 0;
2690 }
2691 EXPORT_SYMBOL(mxc_spdc_fb_set_pwrdown_delay);
2692
2693 int mxc_spdc_get_pwrdown_delay(struct fb_info *info)
2694 {
2695         mxc_spdc_t *fb_data = info ?
2696                 (mxc_spdc_t *)info:g_fb_data;
2697
2698         return fb_data->pwrdown_delay;
2699 }
2700 EXPORT_SYMBOL(mxc_spdc_get_pwrdown_delay);
2701
2702 static int
2703 mxc_spdc_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2704 {
2705         mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
2706         void __user *argp = (void __user *)arg;
2707         int ret = -EINVAL;
2708
2709         dev_dbg(fb_data->dev, "cmd = %08X, arg = %08X\n", cmd, (u32)arg);
2710
2711         switch (cmd) {
2712         case MXCFB_SET_WAVEFORM_MODES:
2713                 {
2714                         struct mxcfb_waveform_modes modes;
2715                         if (!copy_from_user(&modes, argp, sizeof(modes))) {
2716                                 mxc_spdc_fb_set_waveform_modes(&modes, info);
2717                                 ret = 0;
2718                         }
2719                         break;
2720                 }
2721         case MXCFB_SET_TEMPERATURE:
2722                 {
2723                         int temperature;
2724                         if (!get_user(temperature, (int32_t __user *) arg))
2725                                 ret = mxc_spdc_fb_set_temperature(temperature,
2726                                         info);
2727                         break;
2728                 }
2729         case MXCFB_SET_AUTO_UPDATE_MODE:
2730                 {
2731                         u32 auto_mode = 0;
2732                         if (!get_user(auto_mode, (__u32 __user *) arg))
2733                                 ret = mxc_spdc_fb_set_auto_update(auto_mode,
2734                                         info);
2735                         break;
2736                 }
2737         case MXCFB_SET_UPDATE_SCHEME:
2738                 {
2739                         u32 upd_scheme = 0;
2740                         if (!get_user(upd_scheme, (__u32 __user *) arg))
2741                                 ret = mxc_spdc_fb_set_upd_scheme(upd_scheme,
2742                                         info);
2743                         break;
2744                 }
2745         case MXCFB_SEND_UPDATE:
2746                 {
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,
2752                                         sizeof(upd_data)))
2753                                         ret = -EFAULT;
2754                         } else {
2755                                 ret = -EFAULT;
2756                         }
2757
2758                         break;
2759                 }
2760         case MXCFB_WAIT_FOR_UPDATE_COMPLETE:
2761                 {
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)))
2769                                         ret = -EFAULT;
2770                         } else {
2771                                 ret = -EFAULT;
2772                         }
2773
2774                         break;
2775                 }
2776         case MXCFB_SET_PWRDOWN_DELAY:
2777                 {
2778                         int delay = 0;
2779                         if (!get_user(delay, (__u32 __user *) arg))
2780                                 ret =
2781                                 mxc_spdc_fb_set_pwrdown_delay(delay, info);
2782                         break;
2783                 }
2784         case MXCFB_GET_PWRDOWN_DELAY:
2785                 {
2786                         int pwrdown_delay = mxc_spdc_get_pwrdown_delay(info);
2787                         if (put_user(pwrdown_delay, (int __user *)arg))
2788                                 ret = -EFAULT;
2789                         break;
2790                 }
2791         default:
2792                 dev_err(fb_data->dev, "IOCTL_CMD: not such command\n");
2793                 return -ENOTTY;
2794         }
2795
2796         return ret;
2797 }
2798
2799 static void mxc_spdc_fb_update_pages(mxc_spdc_t *fb_data, u16 y1, u16 y2)
2800 {
2801         struct mxcfb_update_data update;
2802
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;
2812         update.flags = 0;
2813
2814         mxc_spdc_fb_send_update(&update, &fb_data->info);
2815 }
2816
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)
2820 {
2821         mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
2822         struct page *page;
2823         unsigned long beg, end;
2824         int y1, y2, miny, maxy;
2825
2826         if (fb_data->auto_mode != AUTO_UPDATE_MODE_AUTOMATIC_MODE)
2827                 return;
2828
2829         miny = INT_MAX;
2830         maxy = 0;
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;
2838                 if (miny > y1)
2839                         miny = y1;
2840                 if (maxy < y2)
2841                         maxy = y2;
2842         }
2843
2844         mxc_spdc_fb_update_pages(fb_data, miny, maxy);
2845 }
2846
2847 static int mxc_spdc_fb_blank(int blank, struct fb_info *info)
2848 {
2849         mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
2850         int ret = 0;
2851
2852         dev_dbg(fb_data->dev, "blank = %d\n", blank);
2853
2854         if (fb_data->blank == blank)
2855                 return 0;
2856
2857         fb_data->blank = blank;
2858         switch (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)) {
2865
2866                         /* Powerdown disabled, so we disable SPDC manually */
2867                         int count = 0;
2868                         int sleep_ms = 10;
2869
2870                         mutex_unlock(&fb_data->power_mutex);
2871
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)
2876                                         break;
2877                                 msleep(sleep_ms);
2878                                 count++;
2879                         }
2880
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);
2887                         ret =
2888                         wait_for_completion_timeout(&fb_data->powerdown_compl,
2889                                 msecs_to_jiffies(5000));
2890                         if (!ret) {
2891                                 dev_err(fb_data->dev,
2892                                         "No powerdown received!\n");
2893                                 return -ETIMEDOUT;
2894                         }
2895                 } else
2896                         mutex_unlock(&fb_data->power_mutex);
2897                 break;
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);
2902                 break;
2903         }
2904
2905         return ret;
2906 }
2907
2908 static int mxc_spdc_fb_pan_display(struct fb_var_screeninfo *var,
2909                                    struct fb_info *info)
2910 {
2911         mxc_spdc_t *fb_data = info ?
2912                 (mxc_spdc_t *)info:g_fb_data;
2913         u_int y_bottom;
2914
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");
2921                 return -EINVAL;
2922         }
2923
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 */
2927
2928         y_bottom = var->yoffset;
2929
2930         if (!(var->vmode & FB_VMODE_YWRAP))
2931                 y_bottom += var->yres;
2932
2933         if (y_bottom > info->var.yres_virtual)
2934                 return -EINVAL;
2935
2936         mutex_lock(&fb_data->queue_mutex);
2937
2938         fb_data->fb_offset = (var->yoffset * var->xres_virtual + var->xoffset)
2939                 * (var->bits_per_pixel) / 8;
2940
2941         fb_data->spdc_fb_var.xoffset = var->xoffset;
2942         fb_data->spdc_fb_var.yoffset = var->yoffset;
2943
2944         if (var->vmode & FB_VMODE_YWRAP)
2945                 info->var.vmode |= FB_VMODE_YWRAP;
2946         else
2947                 info->var.vmode &= ~FB_VMODE_YWRAP;
2948
2949         mutex_unlock(&fb_data->queue_mutex);
2950
2951         return 0;
2952 }
2953
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,
2967 };
2968
2969 static struct fb_deferred_io mxc_spdc_fb_defio = {
2970         .delay = HZ,
2971         .deferred_io = mxc_spdc_fb_deferred_io,
2972 };
2973
2974 static void spdc_done_work_func(struct work_struct *work)
2975 {
2976         mxc_spdc_t *fb_data =
2977                 container_of(work, mxc_spdc_t, spdc_done_work.work);
2978         spdc_powerdown(fb_data);
2979 }
2980
2981 static irqreturn_t mxc_spdc_irq_handler(int irq, void *dev_id)
2982 {
2983         mxc_spdc_t *fb_data = (mxc_spdc_t *)dev_id;
2984         ulong flags;
2985         u32 int_events;
2986         irqreturn_t ret = IRQ_NONE;
2987
2988         spin_lock_irqsave(&fb_data->lock, flags);
2989
2990         int_events = spdc_get_intr_stat(fb_data);
2991         dev_dbg(fb_data->dev, "spdc int:%x\n", int_events);
2992
2993         if (int_events & SPDC_IRQ_STA_ERR) {
2994                 ret = IRQ_HANDLED;
2995                 spdc_intr_stat_clear(fb_data, SPDC_IRQ_STA_ERR);
2996                 dev_err(fb_data->dev, "Error IRQ\n");
2997                 return ret;
2998         }
2999
3000         /*
3001          * If we just completed one-time panel init, bypass
3002          * queue handling, clear interrupt and return
3003          */
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);
3010
3011                 if ((fb_data->operation_mode == SPDC_DEEP_REFRESH) ||
3012                         fb_data->is_deep_fresh)
3013                         fb_data->is_deep_fresh = false;
3014                 else
3015                         fb_data->operation_mode = SPDC_NO_OPERATION;
3016
3017                 mutex_unlock(&fb_data->queue_mutex);
3018
3019                 return IRQ_HANDLED;
3020         }
3021
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);
3028                 } else
3029                         dev_dbg(fb_data->dev, "Lut checksum is err!\n");
3030
3031                 return IRQ_HANDLED;
3032         }
3033
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);
3038
3039                 return IRQ_HANDLED;
3040         }
3041
3042         spin_unlock_irqrestore(&fb_data->lock, flags);
3043
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);
3049         }
3050
3051          return ret;
3052 }
3053
3054 static void spdc_intr_work_func(struct work_struct *work)
3055 {
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;
3062
3063         /* Protect access to buffer queues and to update HW */
3064         mutex_lock(&fb_data->queue_mutex);
3065
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)) {
3070
3071                 fb_data->updates_active = false;
3072
3073                 if (fb_data->pwrdown_delay != FB_POWERDOWN_DISABLE) {
3074                         /*
3075                          * Set variable to prevent overlapping
3076                          * enable/disable requests
3077                          */
3078                         fb_data->powering_down = true;
3079
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));
3083
3084                         /* Reset counter to reduce chance of overflow */
3085                         fb_data->order_cnt = 0;
3086                 }
3087
3088                 if (fb_data->waiting_for_idle)
3089                         complete(&fb_data->updates_done);
3090         }
3091
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);
3095                 return;
3096         }
3097
3098         /*
3099          * Were we waiting on working buffer?
3100          * If so, update queues and check for collisions
3101          */
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,
3105                         upd_list) {
3106
3107                         /* Del from per-update & full list */
3108                         list_del_init(&next_marker->upd_list);
3109                         list_del_init(&next_marker->full_list);
3110
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);
3117                         else
3118                                 kfree(next_marker);
3119                 }
3120
3121                 /* Free marker list and update descriptor */
3122                 kfree(fb_data->cur_update->update_desc);
3123
3124                 /* Add to free buffer list */
3125                 list_add_tail(&fb_data->cur_update->list,
3126                          &fb_data->upd_buf_free_list);
3127
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);
3131                 }
3132
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);
3139
3140                         list_del_init(&next_marker->upd_list);
3141                         list_del_init(&next_marker->full_list);
3142
3143                         /* Signal completion of update */
3144                         dev_dbg(fb_data->dev,
3145                                 "Signaling marker %d\n",
3146                                 next_marker->update_marker);
3147
3148                         if (next_marker->waiting)
3149                                 complete(&next_marker->update_completion);
3150                         else
3151                                 kfree(next_marker);
3152
3153
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);
3159                 }
3160
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)) {
3164
3165                         fb_data->updates_active = false;
3166
3167                         if (fb_data->pwrdown_delay !=
3168                                         FB_POWERDOWN_DISABLE) {
3169                                 /*
3170                                  * Set variable to prevent overlapping
3171                                  * enable/disable requests
3172                                  */
3173                                 fb_data->powering_down = true;
3174
3175                                 /* Schedule SPDC disable */
3176                                 schedule_delayed_work(&fb_data->spdc_done_work,
3177                                 msecs_to_jiffies(fb_data->pwrdown_delay));
3178
3179                                 /* Reset counter to reduce chance of overflow */
3180                                 fb_data->order_cnt = 0;
3181                         }
3182
3183                         if (fb_data->waiting_for_idle)
3184                                 complete(&fb_data->updates_done);
3185                 }
3186
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;
3192                 }
3193
3194                 /* Clear current update */
3195                 fb_data->cur_update = NULL;
3196         }
3197
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);
3204
3205                 /* Release buffer queues */
3206                 mutex_unlock(&fb_data->queue_mutex);
3207                 return;
3208         }
3209
3210         /* Snapshot update scheme processing */
3211         if (list_empty(&fb_data->upd_buf_queue)) {
3212                 dev_dbg(fb_data->dev, "No pending updates.\n");
3213
3214                 /* No updates pending, so we are done */
3215                 mutex_unlock(&fb_data->queue_mutex);
3216                 return;
3217         } else {
3218                 dev_dbg(fb_data->dev, "Found a pending update!\n");
3219
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);
3225         }
3226
3227         /* program SPDC register and trigger to process buffer*/
3228         next_upd_region =
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);
3233
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);
3243
3244         mutex_unlock(&fb_data->queue_mutex);
3245
3246         return;
3247 }
3248
3249 /*
3250  * Sysfs functions
3251  */
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;
3256
3257         return sprintf(buf, "mode%d\n", fb_data->fresh_param.wave_mode);
3258 }
3259
3260 static ssize_t store_update(struct device *device,
3261                          struct device_attribute *attr,
3262                          const char *buf, size_t count)
3263 {
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;
3279
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;
3288         update.flags = 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);
3291
3292         mxc_spdc_fb_send_update(&update, info);
3293
3294         return count;
3295 }
3296
3297 static ssize_t fresh_show(struct device *device, struct device_attribute *attr,
3298                           char *buf)
3299 {
3300         struct fb_info *info = dev_get_drvdata(device);
3301         mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
3302
3303         return sprintf(buf, "%d\n", fb_data->operation_mode);
3304 }
3305
3306 static ssize_t fresh_store(struct device *device, struct device_attribute *attr,
3307                            const char *buf, size_t count)
3308 {
3309         struct fb_info *info = dev_get_drvdata(device);
3310         mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
3311         int ret, operation;
3312
3313         ret = kstrtoint(buf, 10, &operation);
3314         if (ret)
3315                 return ret;
3316
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);
3323         else
3324                 mxc_spdc_refresh_display(fb_data);
3325
3326         return count;
3327 }
3328
3329 static ssize_t temp_show(struct device *device,
3330                 struct device_attribute *attr, char *buf)
3331 {
3332         struct fb_info *info = dev_get_drvdata(device);
3333         mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
3334         int temp;
3335
3336         temp = fb_data->fresh_param.temper >> 1;
3337         return sprintf(buf, "%d\n", temp);
3338 }
3339
3340 static ssize_t initset_show(struct device *device,
3341                 struct device_attribute *attr, char *buf)
3342 {
3343         struct fb_info *info = dev_get_drvdata(device);
3344         mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
3345         u32 init_val;
3346
3347         get_panel_init_set(&fb_data->panel_set, &init_val);
3348         return sprintf(buf, "%x\n", init_val);
3349 }
3350
3351 static ssize_t concurrency_show(struct device *device,
3352                 struct device_attribute *attr, char *buf)
3353 {
3354         struct fb_info *info = dev_get_drvdata(device);
3355         mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
3356         bool temp;
3357
3358         temp = (fb_data->fresh_param.concur ? 1 : 0);
3359         return sprintf(buf, "%d\n", temp);
3360 }
3361
3362 static ssize_t concurrency_update(struct device *device,
3363         struct device_attribute *attr, const char *buf, size_t count)
3364 {
3365         struct fb_info *info = dev_get_drvdata(device);
3366         mxc_spdc_t *fb_data = (mxc_spdc_t *)info;
3367         int ret, concur;
3368
3369         ret = kstrtoint(buf, 10, &concur);
3370         if (ret)
3371                 return ret;
3372
3373         if (fb_data->fresh_param.concur != concur) {
3374                 fb_data->fresh_param.concur = concur;
3375                 spdc_set_update_concurrency(fb_data);
3376         }
3377
3378         return count;
3379 }
3380
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);
3386
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,
3393         NULL
3394 };
3395
3396 static const struct attribute_group spdc_attr_group = {
3397         .attrs = spdc_attributes,
3398 };
3399
3400 static int __devinit mxc_spdc_fb_probe(struct platform_device *pdev)
3401 {
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;
3419         u32 i, cmap_size;
3420         int ret = 0;
3421
3422         fb_data = (mxc_spdc_t *)framebuffer_alloc(sizeof(mxc_spdc_t),
3423                                                         &pdev->dev);
3424         if (!fb_data) {
3425                 ret = -ENOMEM;
3426                 goto out;
3427         }
3428
3429         info = &fb_data->info;
3430         fb_data->dev = &pdev->dev;
3431         platform_set_drvdata(pdev, fb_data);
3432
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)) {
3437                 ret = -EINVAL;
3438                 goto dealloc_fb;
3439         }
3440
3441         /*get panel para from command*/
3442         if (fb_get_options(name, &options)) {
3443                 ret = -ENODEV;
3444                 goto dealloc_fb;
3445         }
3446         if (options)
3447                 while ((opt = strsep(&options, ",")) != NULL) {
3448                         if (!*opt)
3449                                 continue;
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);
3456                         else
3457                                 panel_str = opt;
3458                 }
3459
3460         if (!fb_data->default_bpp)
3461                 fb_data->default_bpp = SPDC_DEFAULT_BPP;
3462
3463         /* Set default (first defined mode) for a match */
3464         mxc_spdc_find_match_mode(fb_data);
3465
3466         if (panel_str)
3467                 for (i = 0; i < fb_data->pdata->num_modes; i++)
3468                         if (!strcmp(fb_data->pdata->spdc_mode[i].vmode->name,
3469                                                         panel_str)) {
3470                                 fb_data->cur_mode =
3471                                          &fb_data->pdata->spdc_mode[i];
3472                                 break;
3473                         }
3474         vmode = fb_data->cur_mode->vmode;
3475
3476         /* Allocate color map for the FB */
3477         cmap_size = 256;
3478         ret = fb_alloc_cmap(&info->cmap, cmap_size, 0);
3479         if (ret)
3480                 goto dealloc_fb;
3481
3482         /*
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
3487          */
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);
3491
3492         /*
3493          * Have to check to see if aligned buffer size when rotated
3494          * is bigger than when not rotated, and use the max
3495          */
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;
3502
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;
3510         } else
3511                 fb_data->num_screens = NUM_SCREENS_MIN;
3512
3513         fb_data->map_size = buf_size * fb_data->num_screens;
3514         dev_dbg(&pdev->dev, "memory allocate: %d\n", fb_data->map_size);
3515
3516         /* get IO memory*/
3517         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3518         if (res == NULL) {
3519                 dev_err(&pdev->dev, "failed to get memory register\n");
3520                 ret = -ENXIO;
3521                 goto release_cmap;
3522         }
3523
3524         mem = request_mem_region(res->start, resource_size(res), pdev->name);
3525         if (res == NULL) {
3526                 dev_err(&pdev->dev, "failed to get memory region\n");
3527                 ret = -ENOENT;
3528                 goto release_cmap;
3529         }
3530
3531         fb_data->hwp = ioremap(res->start, SZ_4K);
3532         if (fb_data->hwp == NULL) {
3533                 dev_err(&pdev->dev, "ioremap registers failed\n");
3534                 ret = -ENOENT;
3535                 goto release_mem;
3536         }
3537
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");
3543                 ret = -ENOMEM;
3544                 goto release_hwp;
3545         }
3546
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;
3562
3563         switch (fb_data->default_bpp) {
3564         case 32:
3565         case 24:
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;
3572                 break;
3573         case 16:
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;
3580                 break;
3581         case 8:
3582                 var_info->grayscale = GRAYSCALE_8BIT;
3583
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;
3593                 break;
3594         case 4:
3595                 var_info->grayscale = GRAYSCALE_4BIT;
3596
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;
3606                 break;
3607         default:
3608                 dev_err(&pdev->dev, "unsupported bit-width:%d\n",
3609                         fb_data->default_bpp);
3610                 ret = -EINVAL;
3611                 goto release_dma_fb;
3612         }
3613
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;
3625
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;
3635
3636         mxc_spdc_fb_set_fix(info);
3637
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);
3643                 ret = -ENODEV;
3644                 goto release_dma_fb;
3645         }
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);
3650                 ret = -ENODEV;
3651                 goto release_dma_fb;
3652         }
3653
3654         /*
3655          * Initialize update list and allocate buffer.
3656          */
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);
3662
3663         fb_data->max_num_updates = SPDC_MAX_NUM_UPDATES;
3664         fb_data->max_num_buffers = SPDC_MAX_NUM_BUFFERS;
3665
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) {
3670                         ret = -ENOMEM;
3671                         goto release_dma_fb;
3672                 }
3673
3674                 /* Add newly allocated buffer to free list */
3675                 list_add(&upd_list->list, &fb_data->upd_buf_free_list);
3676         }
3677
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,
3683                         GFP_KERNEL);
3684         for (i = 0; i < fb_data->max_num_buffers; i++) {
3685                 /*
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
3690                  */
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) {
3696                         ret = -ENOMEM;
3697                         goto release_freebuf_lists;
3698                 }
3699         }
3700         /* Counter indicating which update buffer should be used next. */
3701         fb_data->upd_buffer_num = 0;
3702
3703         /* Allocate memory for partical process region buffer.
3704          *  Output raw data is Y4 format.
3705          */
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) {
3711                 ret = -ENOMEM;
3712                 goto release_output_buf;
3713         }
3714
3715         /* Allocate next & current & privious & count & lut buffers.
3716          *  next buffer size is Y4 raw data
3717          */
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");
3725                 ret = -ENOMEM;
3726                 goto release_copy_buf;
3727         }
3728
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");
3736                 ret = -ENOMEM;
3737                 goto release_next_buf;
3738         }
3739
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");
3747                 ret = -ENOMEM;
3748                 goto release_current_buf;
3749         }
3750
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");
3757                 ret = -ENOMEM;
3758                 goto release_pre_buf;
3759         }
3760
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");
3767                 ret = -ENOMEM;
3768                 goto release_cnt_buf;
3769         }
3770
3771         /* Initialize SPDC pins */
3772         if (fb_data->pdata->get_pins)
3773                 fb_data->pdata->get_pins();
3774
3775         fb_data->hw_ready = false;
3776         fb_data->hw_initializing = false;
3777
3778         /*
3779          * Set default waveform mode values.
3780          * Should be overwritten via ioctl.
3781          */
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;
3788
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;
3793
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;
3804
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);
3813
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);
3822
3823         /* Retrieve spdc IRQ num */
3824         res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
3825         if (res == NULL) {
3826                 dev_err(&pdev->dev, "cannot get IRQ resource\n");
3827                 ret = -ENODEV;
3828                 goto release_lut_buf;
3829         }
3830         fb_data->spdc_irq = res->start;
3831         ret = request_irq(fb_data->spdc_irq, mxc_spdc_irq_handler, 0,
3832                         "fb_dma", fb_data);
3833         if (ret) {
3834                 dev_err(&pdev->dev, "request_irq (%d) failed with error %d\n",
3835                         fb_data->spdc_irq, ret);
3836                 ret = -ENODEV;
3837                 goto release_lut_buf;
3838         }
3839
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);
3844 #endif
3845
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);
3851                 ret = -ENODEV;
3852                 goto release_irq;
3853         }
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);
3859                 ret = -ENODEV;
3860                 goto release_regulator1;
3861         }
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);
3868                 ret = -ENODEV;
3869                 goto release_regulator2;
3870         }
3871
3872         /*
3873          * Fill out PxP config data structure based on FB info and
3874          * processing tasks required
3875          */
3876         pxp_conf = &fb_data->pxp_conf;
3877         proc_data = &pxp_conf->proc_data;
3878
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;
3894
3895         /*
3896          * We initially configure PxP for RGB->YUV conversion,
3897          * and only write out Y component of the result.
3898          */
3899
3900         /*
3901          * Initialize S0 channel parameters
3902          * Parameters should match FB format/width/height
3903          */
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;
3909
3910         /*
3911          * Initialize OL0 channel parameters
3912          * No overlay will be used for PxP operation
3913          */
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;
3924         }
3925
3926         /*
3927          * Initialize Output channel parameters
3928          * Output is Y-only greyscale
3929          * Output width/height will vary based on update region size
3930          */
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;
3935
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");
3940                 ret = -ENOMEM;
3941                 goto release_regulator3;
3942         }
3943         for (i = 0; i < 256; i++)
3944                 fb_data->pxp_conf.proc_data.lut_map[i] = i;
3945
3946         fb_data->pxp_conf.proc_data.lut_map_updated = true;
3947
3948         /*
3949          * Ensure this is set to NULL here...we will initialize pxp_chan
3950          * later in our thread.
3951          */
3952         fb_data->pxp_chan = NULL;
3953
3954         /* Initialize Scatter-gather list containing 2 buffer addresses. */
3955         sg = fb_data->sg;
3956         sg_init_table(sg, 2);
3957
3958         /*
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)
3962          */
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));
3966
3967         /* Register FB */
3968         ret = register_framebuffer(info);
3969         if (ret) {
3970                 dev_err(&pdev->dev,
3971                         "register framebuffer failed\n");
3972                 goto release_lutmap;
3973         }
3974
3975         ret = sysfs_create_group(&info->device->kobj, &spdc_attr_group);
3976         if (ret)
3977                 dev_err(&pdev->dev, "Unable to create file from fb_attrs\n");
3978
3979         /* use for spdc test */
3980         g_fb_data = fb_data;
3981
3982         /* hw init */
3983         spdc_fb_dev_init(fb_data);
3984
3985         /*detect spdc epd disp & tcon version*/
3986         get_spdc_version(fb_data);
3987
3988         goto out;
3989
3990 release_lutmap:
3991         kfree(fb_data->pxp_conf.proc_data.lut_map);
3992 release_regulator3:
3993         regulator_put(fb_data->v3p3_regulator);
3994 release_regulator2:
3995         regulator_put(fb_data->vcom_regulator);
3996 release_regulator1:
3997         regulator_put(fb_data->display_regulator);
3998 release_irq:
3999         free_irq(fb_data->spdc_irq, fb_data);
4000 release_lut_buf:
4001         dma_free_coherent(&pdev->dev, fb_data->pre_buf_size,
4002                 fb_data->virt_lut_buf, fb_data->phy_lut_buf);
4003 release_cnt_buf:
4004         dma_free_coherent(&pdev->dev, fb_data->cnt_buf_size,
4005                 fb_data->virt_cnt_buf, fb_data->phy_cnt_buf);
4006 release_pre_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);
4012 release_next_buf:
4013         dma_free_coherent(&pdev->dev, fb_data->next_buf_size,
4014                 fb_data->virt_next_buf, fb_data->phy_next_buf);
4015 release_copy_buf:
4016         dma_free_writecombine(&pdev->dev, fb_data->max_pix_size / 2,
4017                 fb_data->virt_addr_copybuf, fb_data->phys_addr_copybuf);
4018 release_output_buf:
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,
4030                         list) {
4031                 list_del(&plist->list);
4032                 kfree(plist);
4033         }
4034 release_dma_fb:
4035         dma_free_writecombine(&pdev->dev,
4036         fb_data->map_size, fb_data->virt_start, fb_data->phys_start);
4037 release_hwp:
4038         iounmap(fb_data->hwp);
4039 release_mem:
4040         release_resource(mem);
4041 release_cmap:
4042         fb_dealloc_cmap(&info->cmap);
4043 dealloc_fb:
4044         framebuffer_release(info);
4045 out:
4046         return ret;
4047 }
4048
4049 static int mxc_spdc_fb_remove(struct platform_device *pdev)
4050 {
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;
4054         int i;
4055
4056         mxc_spdc_fb_blank(FB_BLANK_POWERDOWN, &fb_data->info);
4057
4058         flush_workqueue(fb_data->spdc_submit_workqueue);
4059         destroy_workqueue(fb_data->spdc_submit_workqueue);
4060
4061         regulator_put(fb_data->display_regulator);
4062         regulator_put(fb_data->vcom_regulator);
4063         regulator_put(fb_data->v3p3_regulator);
4064
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);
4075
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);
4079
4080         list_for_each_entry_safe(plist, temp_list,
4081                         &fb_data->upd_buf_free_list,
4082                         list) {
4083                 list_del(&plist->list);
4084                 kfree(plist);
4085         }
4086
4087 #if defined(CONFIG_FB_MXC_SIPIX_AUTO_UPDATE_MODE)
4088         fb_deferred_io_cleanup(&fb_data->info);
4089 #endif
4090
4091         /* free frame buffer */
4092         dma_free_writecombine(&pdev->dev, fb_data->map_size,
4093                         info->screen_base, fb_data->phys_start);
4094
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);
4106
4107         sysfs_remove_group(&info->device->kobj, &spdc_attr_group);
4108         unregister_framebuffer(info);
4109
4110         if (fb_data->pdata->put_pins)
4111                 fb_data->pdata->put_pins();
4112
4113         free_irq(fb_data->spdc_irq, fb_data);
4114         iounmap(fb_data->hwp);
4115
4116         fb_dealloc_cmap(&info->cmap);
4117
4118         framebuffer_release(info);
4119         platform_set_drvdata(pdev, NULL);
4120
4121         return 0;
4122 }
4123
4124 #ifdef CONFIG_PM
4125 static int mxc_spdc_fb_suspend(struct platform_device *pdev,
4126                                 pm_message_t state)
4127 {
4128         mxc_spdc_t *data = platform_get_drvdata(pdev);
4129         int ret;
4130
4131         ret = mxc_spdc_fb_blank(FB_BLANK_POWERDOWN, &data->info);
4132
4133         return ret;
4134 }
4135
4136 static int mxc_spdc_fb_resume(struct platform_device *pdev)
4137 {
4138         mxc_spdc_t *data = platform_get_drvdata(pdev);
4139
4140         mxc_spdc_fb_blank(FB_BLANK_UNBLANK, &data->info);
4141         return 0;
4142 }
4143 #else
4144 #define mxc_spdc_fb_suspend     NULL
4145 #define mxc_spdc_fb_resume      NULL
4146 #endif
4147
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,
4153         .driver = {
4154                 .name = SPDC_DRIVER_NAME,
4155                 .owner = THIS_MODULE,
4156         },
4157 };
4158
4159 static int __init mxc_spdc_fb_init(void)
4160 {
4161         return platform_driver_register(&mxc_spdc_fb_driver);
4162 }
4163 late_initcall(mxc_spdc_fb_init);
4164
4165 static void __exit mxc_spdc_fb_exit(void)
4166 {
4167         platform_driver_unregister(&mxc_spdc_fb_driver);
4168 }
4169 module_exit(mxc_spdc_fb_exit);
4170
4171 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
4172 MODULE_DESCRIPTION("MXC SPDC framebuffer driver");
4173 MODULE_LICENSE("GPL");
4174 MODULE_SUPPORTED_DEVICE("fb");