]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/media/video/davinci/vpbe_osd.c
Merge branches 'core-urgent-for-linus', 'perf-urgent-for-linus', 'sched-urgent-for...
[karo-tx-linux.git] / drivers / media / video / davinci / vpbe_osd.c
1 /*
2  * Copyright (C) 2007-2010 Texas Instruments Inc
3  * Copyright (C) 2007 MontaVista Software, Inc.
4  *
5  * Andy Lowe (alowe@mvista.com), MontaVista Software
6  * - Initial version
7  * Murali Karicheri (mkaricheri@gmail.com), Texas Instruments Ltd.
8  * - ported to sub device interface
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation version 2.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24 #include <linux/module.h>
25 #include <linux/kernel.h>
26 #include <linux/interrupt.h>
27 #include <linux/platform_device.h>
28 #include <linux/clk.h>
29 #include <linux/slab.h>
30
31 #include <mach/io.h>
32 #include <mach/cputype.h>
33 #include <mach/hardware.h>
34
35 #include <media/davinci/vpss.h>
36 #include <media/v4l2-device.h>
37 #include <media/davinci/vpbe_types.h>
38 #include <media/davinci/vpbe_osd.h>
39
40 #include <linux/io.h>
41 #include "vpbe_osd_regs.h"
42
43 #define MODULE_NAME     VPBE_OSD_SUBDEV_NAME
44
45 /* register access routines */
46 static inline u32 osd_read(struct osd_state *sd, u32 offset)
47 {
48         struct osd_state *osd = sd;
49
50         return readl(osd->osd_base + offset);
51 }
52
53 static inline u32 osd_write(struct osd_state *sd, u32 val, u32 offset)
54 {
55         struct osd_state *osd = sd;
56
57         writel(val, osd->osd_base + offset);
58
59         return val;
60 }
61
62 static inline u32 osd_set(struct osd_state *sd, u32 mask, u32 offset)
63 {
64         struct osd_state *osd = sd;
65
66         u32 addr = osd->osd_base + offset;
67         u32 val = readl(addr) | mask;
68
69         writel(val, addr);
70
71         return val;
72 }
73
74 static inline u32 osd_clear(struct osd_state *sd, u32 mask, u32 offset)
75 {
76         struct osd_state *osd = sd;
77
78         u32 addr = osd->osd_base + offset;
79         u32 val = readl(addr) & ~mask;
80
81         writel(val, addr);
82
83         return val;
84 }
85
86 static inline u32 osd_modify(struct osd_state *sd, u32 mask, u32 val,
87                                  u32 offset)
88 {
89         struct osd_state *osd = sd;
90
91         u32 addr = osd->osd_base + offset;
92         u32 new_val = (readl(addr) & ~mask) | (val & mask);
93
94         writel(new_val, addr);
95
96         return new_val;
97 }
98
99 /* define some macros for layer and pixfmt classification */
100 #define is_osd_win(layer) (((layer) == WIN_OSD0) || ((layer) == WIN_OSD1))
101 #define is_vid_win(layer) (((layer) == WIN_VID0) || ((layer) == WIN_VID1))
102 #define is_rgb_pixfmt(pixfmt) \
103         (((pixfmt) == PIXFMT_RGB565) || ((pixfmt) == PIXFMT_RGB888))
104 #define is_yc_pixfmt(pixfmt) \
105         (((pixfmt) == PIXFMT_YCbCrI) || ((pixfmt) == PIXFMT_YCrCbI) || \
106         ((pixfmt) == PIXFMT_NV12))
107 #define MAX_WIN_SIZE OSD_VIDWIN0XP_V0X
108 #define MAX_LINE_LENGTH (OSD_VIDWIN0OFST_V0LO << 5)
109
110 /**
111  * _osd_dm6446_vid0_pingpong() - field inversion fix for DM6446
112  * @sd - ptr to struct osd_state
113  * @field_inversion - inversion flag
114  * @fb_base_phys - frame buffer address
115  * @lconfig - ptr to layer config
116  *
117  * This routine implements a workaround for the field signal inversion silicon
118  * erratum described in Advisory 1.3.8 for the DM6446.  The fb_base_phys and
119  * lconfig parameters apply to the vid0 window.  This routine should be called
120  * whenever the vid0 layer configuration or start address is modified, or when
121  * the OSD field inversion setting is modified.
122  * Returns: 1 if the ping-pong buffers need to be toggled in the vsync isr, or
123  *          0 otherwise
124  */
125 static int _osd_dm6446_vid0_pingpong(struct osd_state *sd,
126                                      int field_inversion,
127                                      unsigned long fb_base_phys,
128                                      const struct osd_layer_config *lconfig)
129 {
130         struct osd_platform_data *pdata;
131
132         pdata = (struct osd_platform_data *)sd->dev->platform_data;
133         if (pdata->field_inv_wa_enable) {
134
135                 if (!field_inversion || !lconfig->interlaced) {
136                         osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR);
137                         osd_write(sd, fb_base_phys & ~0x1F, OSD_PPVWIN0ADR);
138                         osd_modify(sd, OSD_MISCCTL_PPSW | OSD_MISCCTL_PPRV, 0,
139                                    OSD_MISCCTL);
140                         return 0;
141                 } else {
142                         unsigned miscctl = OSD_MISCCTL_PPRV;
143
144                         osd_write(sd,
145                                 (fb_base_phys & ~0x1F) - lconfig->line_length,
146                                 OSD_VIDWIN0ADR);
147                         osd_write(sd,
148                                 (fb_base_phys & ~0x1F) + lconfig->line_length,
149                                 OSD_PPVWIN0ADR);
150                         osd_modify(sd,
151                                 OSD_MISCCTL_PPSW | OSD_MISCCTL_PPRV, miscctl,
152                                 OSD_MISCCTL);
153
154                         return 1;
155                 }
156         }
157
158         return 0;
159 }
160
161 static void _osd_set_field_inversion(struct osd_state *sd, int enable)
162 {
163         unsigned fsinv = 0;
164
165         if (enable)
166                 fsinv = OSD_MODE_FSINV;
167
168         osd_modify(sd, OSD_MODE_FSINV, fsinv, OSD_MODE);
169 }
170
171 static void _osd_set_blink_attribute(struct osd_state *sd, int enable,
172                                      enum osd_blink_interval blink)
173 {
174         u32 osdatrmd = 0;
175
176         if (enable) {
177                 osdatrmd |= OSD_OSDATRMD_BLNK;
178                 osdatrmd |= blink << OSD_OSDATRMD_BLNKINT_SHIFT;
179         }
180         /* caller must ensure that OSD1 is configured in attribute mode */
181         osd_modify(sd, OSD_OSDATRMD_BLNKINT | OSD_OSDATRMD_BLNK, osdatrmd,
182                   OSD_OSDATRMD);
183 }
184
185 static void _osd_set_rom_clut(struct osd_state *sd,
186                               enum osd_rom_clut rom_clut)
187 {
188         if (rom_clut == ROM_CLUT0)
189                 osd_clear(sd, OSD_MISCCTL_RSEL, OSD_MISCCTL);
190         else
191                 osd_set(sd, OSD_MISCCTL_RSEL, OSD_MISCCTL);
192 }
193
194 static void _osd_set_palette_map(struct osd_state *sd,
195                                  enum osd_win_layer osdwin,
196                                  unsigned char pixel_value,
197                                  unsigned char clut_index,
198                                  enum osd_pix_format pixfmt)
199 {
200         static const int map_2bpp[] = { 0, 5, 10, 15 };
201         static const int map_1bpp[] = { 0, 15 };
202         int bmp_offset;
203         int bmp_shift;
204         int bmp_mask;
205         int bmp_reg;
206
207         switch (pixfmt) {
208         case PIXFMT_1BPP:
209                 bmp_reg = map_1bpp[pixel_value & 0x1];
210                 break;
211         case PIXFMT_2BPP:
212                 bmp_reg = map_2bpp[pixel_value & 0x3];
213                 break;
214         case PIXFMT_4BPP:
215                 bmp_reg = pixel_value & 0xf;
216                 break;
217         default:
218                 return;
219         }
220
221         switch (osdwin) {
222         case OSDWIN_OSD0:
223                 bmp_offset = OSD_W0BMP01 + (bmp_reg >> 1) * sizeof(u32);
224                 break;
225         case OSDWIN_OSD1:
226                 bmp_offset = OSD_W1BMP01 + (bmp_reg >> 1) * sizeof(u32);
227                 break;
228         default:
229                 return;
230         }
231
232         if (bmp_reg & 1) {
233                 bmp_shift = 8;
234                 bmp_mask = 0xff << 8;
235         } else {
236                 bmp_shift = 0;
237                 bmp_mask = 0xff;
238         }
239
240         osd_modify(sd, bmp_mask, clut_index << bmp_shift, bmp_offset);
241 }
242
243 static void _osd_set_rec601_attenuation(struct osd_state *sd,
244                                         enum osd_win_layer osdwin, int enable)
245 {
246         switch (osdwin) {
247         case OSDWIN_OSD0:
248                 osd_modify(sd, OSD_OSDWIN0MD_ATN0E,
249                           enable ? OSD_OSDWIN0MD_ATN0E : 0,
250                           OSD_OSDWIN0MD);
251                 if (sd->vpbe_type == VPBE_VERSION_1)
252                         osd_modify(sd, OSD_OSDWIN0MD_ATN0E,
253                                   enable ? OSD_OSDWIN0MD_ATN0E : 0,
254                                   OSD_OSDWIN0MD);
255                 else if ((sd->vpbe_type == VPBE_VERSION_3) ||
256                            (sd->vpbe_type == VPBE_VERSION_2))
257                         osd_modify(sd, OSD_EXTMODE_ATNOSD0EN,
258                                   enable ? OSD_EXTMODE_ATNOSD0EN : 0,
259                                   OSD_EXTMODE);
260                 break;
261         case OSDWIN_OSD1:
262                 osd_modify(sd, OSD_OSDWIN1MD_ATN1E,
263                           enable ? OSD_OSDWIN1MD_ATN1E : 0,
264                           OSD_OSDWIN1MD);
265                 if (sd->vpbe_type == VPBE_VERSION_1)
266                         osd_modify(sd, OSD_OSDWIN1MD_ATN1E,
267                                   enable ? OSD_OSDWIN1MD_ATN1E : 0,
268                                   OSD_OSDWIN1MD);
269                 else if ((sd->vpbe_type == VPBE_VERSION_3) ||
270                            (sd->vpbe_type == VPBE_VERSION_2))
271                         osd_modify(sd, OSD_EXTMODE_ATNOSD1EN,
272                                   enable ? OSD_EXTMODE_ATNOSD1EN : 0,
273                                   OSD_EXTMODE);
274                 break;
275         }
276 }
277
278 static void _osd_set_blending_factor(struct osd_state *sd,
279                                      enum osd_win_layer osdwin,
280                                      enum osd_blending_factor blend)
281 {
282         switch (osdwin) {
283         case OSDWIN_OSD0:
284                 osd_modify(sd, OSD_OSDWIN0MD_BLND0,
285                           blend << OSD_OSDWIN0MD_BLND0_SHIFT, OSD_OSDWIN0MD);
286                 break;
287         case OSDWIN_OSD1:
288                 osd_modify(sd, OSD_OSDWIN1MD_BLND1,
289                           blend << OSD_OSDWIN1MD_BLND1_SHIFT, OSD_OSDWIN1MD);
290                 break;
291         }
292 }
293
294 static void _osd_enable_rgb888_pixblend(struct osd_state *sd,
295                                         enum osd_win_layer osdwin)
296 {
297
298         osd_modify(sd, OSD_MISCCTL_BLDSEL, 0, OSD_MISCCTL);
299         switch (osdwin) {
300         case OSDWIN_OSD0:
301                 osd_modify(sd, OSD_EXTMODE_OSD0BLDCHR,
302                           OSD_EXTMODE_OSD0BLDCHR, OSD_EXTMODE);
303                 break;
304         case OSDWIN_OSD1:
305                 osd_modify(sd, OSD_EXTMODE_OSD1BLDCHR,
306                           OSD_EXTMODE_OSD1BLDCHR, OSD_EXTMODE);
307                 break;
308         }
309 }
310
311 static void _osd_enable_color_key(struct osd_state *sd,
312                                   enum osd_win_layer osdwin,
313                                   unsigned colorkey,
314                                   enum osd_pix_format pixfmt)
315 {
316         switch (pixfmt) {
317         case PIXFMT_1BPP:
318         case PIXFMT_2BPP:
319         case PIXFMT_4BPP:
320         case PIXFMT_8BPP:
321                 if (sd->vpbe_type == VPBE_VERSION_3) {
322                         switch (osdwin) {
323                         case OSDWIN_OSD0:
324                                 osd_modify(sd, OSD_TRANSPBMPIDX_BMP0,
325                                           colorkey <<
326                                           OSD_TRANSPBMPIDX_BMP0_SHIFT,
327                                           OSD_TRANSPBMPIDX);
328                                 break;
329                         case OSDWIN_OSD1:
330                                 osd_modify(sd, OSD_TRANSPBMPIDX_BMP1,
331                                           colorkey <<
332                                           OSD_TRANSPBMPIDX_BMP1_SHIFT,
333                                           OSD_TRANSPBMPIDX);
334                                 break;
335                         }
336                 }
337                 break;
338         case PIXFMT_RGB565:
339                 if (sd->vpbe_type == VPBE_VERSION_1)
340                         osd_write(sd, colorkey & OSD_TRANSPVAL_RGBTRANS,
341                                   OSD_TRANSPVAL);
342                 else if (sd->vpbe_type == VPBE_VERSION_3)
343                         osd_write(sd, colorkey & OSD_TRANSPVALL_RGBL,
344                                   OSD_TRANSPVALL);
345                 break;
346         case PIXFMT_YCbCrI:
347         case PIXFMT_YCrCbI:
348                 if (sd->vpbe_type == VPBE_VERSION_3)
349                         osd_modify(sd, OSD_TRANSPVALU_Y, colorkey,
350                                    OSD_TRANSPVALU);
351                 break;
352         case PIXFMT_RGB888:
353                 if (sd->vpbe_type == VPBE_VERSION_3) {
354                         osd_write(sd, colorkey & OSD_TRANSPVALL_RGBL,
355                                   OSD_TRANSPVALL);
356                         osd_modify(sd, OSD_TRANSPVALU_RGBU, colorkey >> 16,
357                                   OSD_TRANSPVALU);
358                 }
359                 break;
360         default:
361                 break;
362         }
363
364         switch (osdwin) {
365         case OSDWIN_OSD0:
366                 osd_set(sd, OSD_OSDWIN0MD_TE0, OSD_OSDWIN0MD);
367                 break;
368         case OSDWIN_OSD1:
369                 osd_set(sd, OSD_OSDWIN1MD_TE1, OSD_OSDWIN1MD);
370                 break;
371         }
372 }
373
374 static void _osd_disable_color_key(struct osd_state *sd,
375                                    enum osd_win_layer osdwin)
376 {
377         switch (osdwin) {
378         case OSDWIN_OSD0:
379                 osd_clear(sd, OSD_OSDWIN0MD_TE0, OSD_OSDWIN0MD);
380                 break;
381         case OSDWIN_OSD1:
382                 osd_clear(sd, OSD_OSDWIN1MD_TE1, OSD_OSDWIN1MD);
383                 break;
384         }
385 }
386
387 static void _osd_set_osd_clut(struct osd_state *sd,
388                               enum osd_win_layer osdwin,
389                               enum osd_clut clut)
390 {
391         u32 winmd = 0;
392
393         switch (osdwin) {
394         case OSDWIN_OSD0:
395                 if (clut == RAM_CLUT)
396                         winmd |= OSD_OSDWIN0MD_CLUTS0;
397                 osd_modify(sd, OSD_OSDWIN0MD_CLUTS0, winmd, OSD_OSDWIN0MD);
398                 break;
399         case OSDWIN_OSD1:
400                 if (clut == RAM_CLUT)
401                         winmd |= OSD_OSDWIN1MD_CLUTS1;
402                 osd_modify(sd, OSD_OSDWIN1MD_CLUTS1, winmd, OSD_OSDWIN1MD);
403                 break;
404         }
405 }
406
407 static void _osd_set_zoom(struct osd_state *sd, enum osd_layer layer,
408                           enum osd_zoom_factor h_zoom,
409                           enum osd_zoom_factor v_zoom)
410 {
411         u32 winmd = 0;
412
413         switch (layer) {
414         case WIN_OSD0:
415                 winmd |= (h_zoom << OSD_OSDWIN0MD_OHZ0_SHIFT);
416                 winmd |= (v_zoom << OSD_OSDWIN0MD_OVZ0_SHIFT);
417                 osd_modify(sd, OSD_OSDWIN0MD_OHZ0 | OSD_OSDWIN0MD_OVZ0, winmd,
418                           OSD_OSDWIN0MD);
419                 break;
420         case WIN_VID0:
421                 winmd |= (h_zoom << OSD_VIDWINMD_VHZ0_SHIFT);
422                 winmd |= (v_zoom << OSD_VIDWINMD_VVZ0_SHIFT);
423                 osd_modify(sd, OSD_VIDWINMD_VHZ0 | OSD_VIDWINMD_VVZ0, winmd,
424                           OSD_VIDWINMD);
425                 break;
426         case WIN_OSD1:
427                 winmd |= (h_zoom << OSD_OSDWIN1MD_OHZ1_SHIFT);
428                 winmd |= (v_zoom << OSD_OSDWIN1MD_OVZ1_SHIFT);
429                 osd_modify(sd, OSD_OSDWIN1MD_OHZ1 | OSD_OSDWIN1MD_OVZ1, winmd,
430                           OSD_OSDWIN1MD);
431                 break;
432         case WIN_VID1:
433                 winmd |= (h_zoom << OSD_VIDWINMD_VHZ1_SHIFT);
434                 winmd |= (v_zoom << OSD_VIDWINMD_VVZ1_SHIFT);
435                 osd_modify(sd, OSD_VIDWINMD_VHZ1 | OSD_VIDWINMD_VVZ1, winmd,
436                           OSD_VIDWINMD);
437                 break;
438         }
439 }
440
441 static void _osd_disable_layer(struct osd_state *sd, enum osd_layer layer)
442 {
443         switch (layer) {
444         case WIN_OSD0:
445                 osd_clear(sd, OSD_OSDWIN0MD_OACT0, OSD_OSDWIN0MD);
446                 break;
447         case WIN_VID0:
448                 osd_clear(sd, OSD_VIDWINMD_ACT0, OSD_VIDWINMD);
449                 break;
450         case WIN_OSD1:
451                 /* disable attribute mode as well as disabling the window */
452                 osd_clear(sd, OSD_OSDWIN1MD_OASW | OSD_OSDWIN1MD_OACT1,
453                           OSD_OSDWIN1MD);
454                 break;
455         case WIN_VID1:
456                 osd_clear(sd, OSD_VIDWINMD_ACT1, OSD_VIDWINMD);
457                 break;
458         }
459 }
460
461 static void osd_disable_layer(struct osd_state *sd, enum osd_layer layer)
462 {
463         struct osd_state *osd = sd;
464         struct osd_window_state *win = &osd->win[layer];
465         unsigned long flags;
466
467         spin_lock_irqsave(&osd->lock, flags);
468
469         if (!win->is_enabled) {
470                 spin_unlock_irqrestore(&osd->lock, flags);
471                 return;
472         }
473         win->is_enabled = 0;
474
475         _osd_disable_layer(sd, layer);
476
477         spin_unlock_irqrestore(&osd->lock, flags);
478 }
479
480 static void _osd_enable_attribute_mode(struct osd_state *sd)
481 {
482         /* enable attribute mode for OSD1 */
483         osd_set(sd, OSD_OSDWIN1MD_OASW, OSD_OSDWIN1MD);
484 }
485
486 static void _osd_enable_layer(struct osd_state *sd, enum osd_layer layer)
487 {
488         switch (layer) {
489         case WIN_OSD0:
490                 osd_set(sd, OSD_OSDWIN0MD_OACT0, OSD_OSDWIN0MD);
491                 break;
492         case WIN_VID0:
493                 osd_set(sd, OSD_VIDWINMD_ACT0, OSD_VIDWINMD);
494                 break;
495         case WIN_OSD1:
496                 /* enable OSD1 and disable attribute mode */
497                 osd_modify(sd, OSD_OSDWIN1MD_OASW | OSD_OSDWIN1MD_OACT1,
498                           OSD_OSDWIN1MD_OACT1, OSD_OSDWIN1MD);
499                 break;
500         case WIN_VID1:
501                 osd_set(sd, OSD_VIDWINMD_ACT1, OSD_VIDWINMD);
502                 break;
503         }
504 }
505
506 static int osd_enable_layer(struct osd_state *sd, enum osd_layer layer,
507                             int otherwin)
508 {
509         struct osd_state *osd = sd;
510         struct osd_window_state *win = &osd->win[layer];
511         struct osd_layer_config *cfg = &win->lconfig;
512         unsigned long flags;
513
514         spin_lock_irqsave(&osd->lock, flags);
515
516         /*
517          * use otherwin flag to know this is the other vid window
518          * in YUV420 mode, if is, skip this check
519          */
520         if (!otherwin && (!win->is_allocated ||
521                         !win->fb_base_phys ||
522                         !cfg->line_length ||
523                         !cfg->xsize ||
524                         !cfg->ysize)) {
525                 spin_unlock_irqrestore(&osd->lock, flags);
526                 return -1;
527         }
528
529         if (win->is_enabled) {
530                 spin_unlock_irqrestore(&osd->lock, flags);
531                 return 0;
532         }
533         win->is_enabled = 1;
534
535         if (cfg->pixfmt != PIXFMT_OSD_ATTR)
536                 _osd_enable_layer(sd, layer);
537         else {
538                 _osd_enable_attribute_mode(sd);
539                 _osd_set_blink_attribute(sd, osd->is_blinking, osd->blink);
540         }
541
542         spin_unlock_irqrestore(&osd->lock, flags);
543
544         return 0;
545 }
546
547 #define OSD_SRC_ADDR_HIGH4      0x7800000
548 #define OSD_SRC_ADDR_HIGH7      0x7F0000
549 #define OSD_SRCADD_OFSET_SFT    23
550 #define OSD_SRCADD_ADD_SFT      16
551 #define OSD_WINADL_MASK         0xFFFF
552 #define OSD_WINOFST_MASK        0x1000
553 #define VPBE_REG_BASE           0x80000000
554
555 static void _osd_start_layer(struct osd_state *sd, enum osd_layer layer,
556                              unsigned long fb_base_phys,
557                              unsigned long cbcr_ofst)
558 {
559
560         if (sd->vpbe_type == VPBE_VERSION_1) {
561                 switch (layer) {
562                 case WIN_OSD0:
563                         osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN0ADR);
564                         break;
565                 case WIN_VID0:
566                         osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR);
567                         break;
568                 case WIN_OSD1:
569                         osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN1ADR);
570                         break;
571                 case WIN_VID1:
572                         osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN1ADR);
573                         break;
574               }
575         } else if (sd->vpbe_type == VPBE_VERSION_3) {
576                 unsigned long fb_offset_32 =
577                     (fb_base_phys - VPBE_REG_BASE) >> 5;
578
579                 switch (layer) {
580                 case WIN_OSD0:
581                         osd_modify(sd, OSD_OSDWINADH_O0AH,
582                                   fb_offset_32 >> (OSD_SRCADD_ADD_SFT -
583                                                    OSD_OSDWINADH_O0AH_SHIFT),
584                                   OSD_OSDWINADH);
585                         osd_write(sd, fb_offset_32 & OSD_OSDWIN0ADL_O0AL,
586                                   OSD_OSDWIN0ADL);
587                         break;
588                 case WIN_VID0:
589                         osd_modify(sd, OSD_VIDWINADH_V0AH,
590                                   fb_offset_32 >> (OSD_SRCADD_ADD_SFT -
591                                                    OSD_VIDWINADH_V0AH_SHIFT),
592                                   OSD_VIDWINADH);
593                         osd_write(sd, fb_offset_32 & OSD_VIDWIN0ADL_V0AL,
594                                   OSD_VIDWIN0ADL);
595                         break;
596                 case WIN_OSD1:
597                         osd_modify(sd, OSD_OSDWINADH_O1AH,
598                                   fb_offset_32 >> (OSD_SRCADD_ADD_SFT -
599                                                    OSD_OSDWINADH_O1AH_SHIFT),
600                                   OSD_OSDWINADH);
601                         osd_write(sd, fb_offset_32 & OSD_OSDWIN1ADL_O1AL,
602                                   OSD_OSDWIN1ADL);
603                         break;
604                 case WIN_VID1:
605                         osd_modify(sd, OSD_VIDWINADH_V1AH,
606                                   fb_offset_32 >> (OSD_SRCADD_ADD_SFT -
607                                                    OSD_VIDWINADH_V1AH_SHIFT),
608                                   OSD_VIDWINADH);
609                         osd_write(sd, fb_offset_32 & OSD_VIDWIN1ADL_V1AL,
610                                   OSD_VIDWIN1ADL);
611                         break;
612                 }
613         } else if (sd->vpbe_type == VPBE_VERSION_2) {
614                 struct osd_window_state *win = &sd->win[layer];
615                 unsigned long fb_offset_32, cbcr_offset_32;
616
617                 fb_offset_32 = fb_base_phys - VPBE_REG_BASE;
618                 if (cbcr_ofst)
619                         cbcr_offset_32 = cbcr_ofst;
620                 else
621                         cbcr_offset_32 = win->lconfig.line_length *
622                                          win->lconfig.ysize;
623                 cbcr_offset_32 += fb_offset_32;
624                 fb_offset_32 = fb_offset_32 >> 5;
625                 cbcr_offset_32 = cbcr_offset_32 >> 5;
626                 /*
627                  * DM365: start address is 27-bit long address b26 - b23 are
628                  * in offset register b12 - b9, and * bit 26 has to be '1'
629                  */
630                 if (win->lconfig.pixfmt == PIXFMT_NV12) {
631                         switch (layer) {
632                         case WIN_VID0:
633                         case WIN_VID1:
634                                 /* Y is in VID0 */
635                                 osd_modify(sd, OSD_VIDWIN0OFST_V0AH,
636                                          ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
637                                          (OSD_SRCADD_OFSET_SFT -
638                                          OSD_WINOFST_AH_SHIFT)) |
639                                          OSD_WINOFST_MASK, OSD_VIDWIN0OFST);
640                                 osd_modify(sd, OSD_VIDWINADH_V0AH,
641                                           (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
642                                           (OSD_SRCADD_ADD_SFT -
643                                           OSD_VIDWINADH_V0AH_SHIFT),
644                                            OSD_VIDWINADH);
645                                 osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
646                                           OSD_VIDWIN0ADL);
647                                 /* CbCr is in VID1 */
648                                 osd_modify(sd, OSD_VIDWIN1OFST_V1AH,
649                                          ((cbcr_offset_32 &
650                                          OSD_SRC_ADDR_HIGH4) >>
651                                          (OSD_SRCADD_OFSET_SFT -
652                                          OSD_WINOFST_AH_SHIFT)) |
653                                          OSD_WINOFST_MASK, OSD_VIDWIN1OFST);
654                                 osd_modify(sd, OSD_VIDWINADH_V1AH,
655                                           (cbcr_offset_32 &
656                                           OSD_SRC_ADDR_HIGH7) >>
657                                           (OSD_SRCADD_ADD_SFT -
658                                           OSD_VIDWINADH_V1AH_SHIFT),
659                                           OSD_VIDWINADH);
660                                 osd_write(sd, cbcr_offset_32 & OSD_WINADL_MASK,
661                                           OSD_VIDWIN1ADL);
662                                 break;
663                         default:
664                                 break;
665                         }
666                 }
667
668                 switch (layer) {
669                 case WIN_OSD0:
670                         osd_modify(sd, OSD_OSDWIN0OFST_O0AH,
671                                  ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
672                                  (OSD_SRCADD_OFSET_SFT -
673                                  OSD_WINOFST_AH_SHIFT)) | OSD_WINOFST_MASK,
674                                   OSD_OSDWIN0OFST);
675                         osd_modify(sd, OSD_OSDWINADH_O0AH,
676                                  (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
677                                  (OSD_SRCADD_ADD_SFT -
678                                  OSD_OSDWINADH_O0AH_SHIFT), OSD_OSDWINADH);
679                         osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
680                                         OSD_OSDWIN0ADL);
681                         break;
682                 case WIN_VID0:
683                         if (win->lconfig.pixfmt != PIXFMT_NV12) {
684                                 osd_modify(sd, OSD_VIDWIN0OFST_V0AH,
685                                          ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
686                                          (OSD_SRCADD_OFSET_SFT -
687                                          OSD_WINOFST_AH_SHIFT)) |
688                                          OSD_WINOFST_MASK, OSD_VIDWIN0OFST);
689                                 osd_modify(sd, OSD_VIDWINADH_V0AH,
690                                           (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
691                                           (OSD_SRCADD_ADD_SFT -
692                                           OSD_VIDWINADH_V0AH_SHIFT),
693                                           OSD_VIDWINADH);
694                                 osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
695                                           OSD_VIDWIN0ADL);
696                         }
697                         break;
698                 case WIN_OSD1:
699                         osd_modify(sd, OSD_OSDWIN1OFST_O1AH,
700                                  ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
701                                  (OSD_SRCADD_OFSET_SFT -
702                                  OSD_WINOFST_AH_SHIFT)) | OSD_WINOFST_MASK,
703                                   OSD_OSDWIN1OFST);
704                         osd_modify(sd, OSD_OSDWINADH_O1AH,
705                                   (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
706                                   (OSD_SRCADD_ADD_SFT -
707                                   OSD_OSDWINADH_O1AH_SHIFT),
708                                   OSD_OSDWINADH);
709                         osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
710                                         OSD_OSDWIN1ADL);
711                         break;
712                 case WIN_VID1:
713                         if (win->lconfig.pixfmt != PIXFMT_NV12) {
714                                 osd_modify(sd, OSD_VIDWIN1OFST_V1AH,
715                                          ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
716                                          (OSD_SRCADD_OFSET_SFT -
717                                          OSD_WINOFST_AH_SHIFT)) |
718                                          OSD_WINOFST_MASK, OSD_VIDWIN1OFST);
719                                 osd_modify(sd, OSD_VIDWINADH_V1AH,
720                                           (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
721                                           (OSD_SRCADD_ADD_SFT -
722                                           OSD_VIDWINADH_V1AH_SHIFT),
723                                           OSD_VIDWINADH);
724                                 osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
725                                           OSD_VIDWIN1ADL);
726                         }
727                         break;
728                 }
729         }
730 }
731
732 static void osd_start_layer(struct osd_state *sd, enum osd_layer layer,
733                             unsigned long fb_base_phys,
734                             unsigned long cbcr_ofst)
735 {
736         struct osd_state *osd = sd;
737         struct osd_window_state *win = &osd->win[layer];
738         struct osd_layer_config *cfg = &win->lconfig;
739         unsigned long flags;
740
741         spin_lock_irqsave(&osd->lock, flags);
742
743         win->fb_base_phys = fb_base_phys & ~0x1F;
744         _osd_start_layer(sd, layer, fb_base_phys, cbcr_ofst);
745
746         if (layer == WIN_VID0) {
747                 osd->pingpong =
748                     _osd_dm6446_vid0_pingpong(sd, osd->field_inversion,
749                                                        win->fb_base_phys,
750                                                        cfg);
751         }
752
753         spin_unlock_irqrestore(&osd->lock, flags);
754 }
755
756 static void osd_get_layer_config(struct osd_state *sd, enum osd_layer layer,
757                                  struct osd_layer_config *lconfig)
758 {
759         struct osd_state *osd = sd;
760         struct osd_window_state *win = &osd->win[layer];
761         unsigned long flags;
762
763         spin_lock_irqsave(&osd->lock, flags);
764
765         *lconfig = win->lconfig;
766
767         spin_unlock_irqrestore(&osd->lock, flags);
768 }
769
770 /**
771  * try_layer_config() - Try a specific configuration for the layer
772  * @sd  - ptr to struct osd_state
773  * @layer - layer to configure
774  * @lconfig - layer configuration to try
775  *
776  * If the requested lconfig is completely rejected and the value of lconfig on
777  * exit is the current lconfig, then try_layer_config() returns 1.  Otherwise,
778  * try_layer_config() returns 0.  A return value of 0 does not necessarily mean
779  * that the value of lconfig on exit is identical to the value of lconfig on
780  * entry, but merely that it represents a change from the current lconfig.
781  */
782 static int try_layer_config(struct osd_state *sd, enum osd_layer layer,
783                             struct osd_layer_config *lconfig)
784 {
785         struct osd_state *osd = sd;
786         struct osd_window_state *win = &osd->win[layer];
787         int bad_config = 0;
788
789         /* verify that the pixel format is compatible with the layer */
790         switch (lconfig->pixfmt) {
791         case PIXFMT_1BPP:
792         case PIXFMT_2BPP:
793         case PIXFMT_4BPP:
794         case PIXFMT_8BPP:
795         case PIXFMT_RGB565:
796                 if (osd->vpbe_type == VPBE_VERSION_1)
797                         bad_config = !is_vid_win(layer);
798                 break;
799         case PIXFMT_YCbCrI:
800         case PIXFMT_YCrCbI:
801                 bad_config = !is_vid_win(layer);
802                 break;
803         case PIXFMT_RGB888:
804                 if (osd->vpbe_type == VPBE_VERSION_1)
805                         bad_config = !is_vid_win(layer);
806                 else if ((osd->vpbe_type == VPBE_VERSION_3) ||
807                          (osd->vpbe_type == VPBE_VERSION_2))
808                         bad_config = !is_osd_win(layer);
809                 break;
810         case PIXFMT_NV12:
811                 if (osd->vpbe_type != VPBE_VERSION_2)
812                         bad_config = 1;
813                 else
814                         bad_config = is_osd_win(layer);
815                 break;
816         case PIXFMT_OSD_ATTR:
817                 bad_config = (layer != WIN_OSD1);
818                 break;
819         default:
820                 bad_config = 1;
821                 break;
822         }
823         if (bad_config) {
824                 /*
825                  * The requested pixel format is incompatible with the layer,
826                  * so keep the current layer configuration.
827                  */
828                 *lconfig = win->lconfig;
829                 return bad_config;
830         }
831
832         /* DM6446: */
833         /* only one OSD window at a time can use RGB pixel formats */
834           if ((osd->vpbe_type == VPBE_VERSION_1) &&
835                   is_osd_win(layer) && is_rgb_pixfmt(lconfig->pixfmt)) {
836                 enum osd_pix_format pixfmt;
837                 if (layer == WIN_OSD0)
838                         pixfmt = osd->win[WIN_OSD1].lconfig.pixfmt;
839                 else
840                         pixfmt = osd->win[WIN_OSD0].lconfig.pixfmt;
841
842                 if (is_rgb_pixfmt(pixfmt)) {
843                         /*
844                          * The other OSD window is already configured for an
845                          * RGB, so keep the current layer configuration.
846                          */
847                         *lconfig = win->lconfig;
848                         return 1;
849                 }
850         }
851
852         /* DM6446: only one video window at a time can use RGB888 */
853         if ((osd->vpbe_type == VPBE_VERSION_1) && is_vid_win(layer) &&
854                 lconfig->pixfmt == PIXFMT_RGB888) {
855                 enum osd_pix_format pixfmt;
856
857                 if (layer == WIN_VID0)
858                         pixfmt = osd->win[WIN_VID1].lconfig.pixfmt;
859                 else
860                         pixfmt = osd->win[WIN_VID0].lconfig.pixfmt;
861
862                 if (pixfmt == PIXFMT_RGB888) {
863                         /*
864                          * The other video window is already configured for
865                          * RGB888, so keep the current layer configuration.
866                          */
867                         *lconfig = win->lconfig;
868                         return 1;
869                 }
870         }
871
872         /* window dimensions must be non-zero */
873         if (!lconfig->line_length || !lconfig->xsize || !lconfig->ysize) {
874                 *lconfig = win->lconfig;
875                 return 1;
876         }
877
878         /* round line_length up to a multiple of 32 */
879         lconfig->line_length = ((lconfig->line_length + 31) / 32) * 32;
880         lconfig->line_length =
881             min(lconfig->line_length, (unsigned)MAX_LINE_LENGTH);
882         lconfig->xsize = min(lconfig->xsize, (unsigned)MAX_WIN_SIZE);
883         lconfig->ysize = min(lconfig->ysize, (unsigned)MAX_WIN_SIZE);
884         lconfig->xpos = min(lconfig->xpos, (unsigned)MAX_WIN_SIZE);
885         lconfig->ypos = min(lconfig->ypos, (unsigned)MAX_WIN_SIZE);
886         lconfig->interlaced = (lconfig->interlaced != 0);
887         if (lconfig->interlaced) {
888                 /* ysize and ypos must be even for interlaced displays */
889                 lconfig->ysize &= ~1;
890                 lconfig->ypos &= ~1;
891         }
892
893         return 0;
894 }
895
896 static void _osd_disable_vid_rgb888(struct osd_state *sd)
897 {
898         /*
899          * The DM6446 supports RGB888 pixel format in a single video window.
900          * This routine disables RGB888 pixel format for both video windows.
901          * The caller must ensure that neither video window is currently
902          * configured for RGB888 pixel format.
903          */
904         if (sd->vpbe_type == VPBE_VERSION_1)
905                 osd_clear(sd, OSD_MISCCTL_RGBEN, OSD_MISCCTL);
906 }
907
908 static void _osd_enable_vid_rgb888(struct osd_state *sd,
909                                    enum osd_layer layer)
910 {
911         /*
912          * The DM6446 supports RGB888 pixel format in a single video window.
913          * This routine enables RGB888 pixel format for the specified video
914          * window.  The caller must ensure that the other video window is not
915          * currently configured for RGB888 pixel format, as this routine will
916          * disable RGB888 pixel format for the other window.
917          */
918         if (sd->vpbe_type == VPBE_VERSION_1) {
919                 if (layer == WIN_VID0)
920                         osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
921                                   OSD_MISCCTL_RGBEN, OSD_MISCCTL);
922                 else if (layer == WIN_VID1)
923                         osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
924                                   OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
925                                   OSD_MISCCTL);
926         }
927 }
928
929 static void _osd_set_cbcr_order(struct osd_state *sd,
930                                 enum osd_pix_format pixfmt)
931 {
932         /*
933          * The caller must ensure that all windows using YC pixfmt use the same
934          * Cb/Cr order.
935          */
936         if (pixfmt == PIXFMT_YCbCrI)
937                 osd_clear(sd, OSD_MODE_CS, OSD_MODE);
938         else if (pixfmt == PIXFMT_YCrCbI)
939                 osd_set(sd, OSD_MODE_CS, OSD_MODE);
940 }
941
942 static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
943                                   const struct osd_layer_config *lconfig)
944 {
945         u32 winmd = 0, winmd_mask = 0, bmw = 0;
946
947         _osd_set_cbcr_order(sd, lconfig->pixfmt);
948
949         switch (layer) {
950         case WIN_OSD0:
951                 if (sd->vpbe_type == VPBE_VERSION_1) {
952                         winmd_mask |= OSD_OSDWIN0MD_RGB0E;
953                         if (lconfig->pixfmt == PIXFMT_RGB565)
954                                 winmd |= OSD_OSDWIN0MD_RGB0E;
955                 } else if ((sd->vpbe_type == VPBE_VERSION_3) ||
956                   (sd->vpbe_type == VPBE_VERSION_2)) {
957                         winmd_mask |= OSD_OSDWIN0MD_BMP0MD;
958                         switch (lconfig->pixfmt) {
959                         case PIXFMT_RGB565:
960                                         winmd |= (1 <<
961                                         OSD_OSDWIN0MD_BMP0MD_SHIFT);
962                                         break;
963                         case PIXFMT_RGB888:
964                                 winmd |= (2 << OSD_OSDWIN0MD_BMP0MD_SHIFT);
965                                 _osd_enable_rgb888_pixblend(sd, OSDWIN_OSD0);
966                                 break;
967                         case PIXFMT_YCbCrI:
968                         case PIXFMT_YCrCbI:
969                                 winmd |= (3 << OSD_OSDWIN0MD_BMP0MD_SHIFT);
970                                 break;
971                         default:
972                                 break;
973                         }
974                 }
975
976                 winmd_mask |= OSD_OSDWIN0MD_BMW0 | OSD_OSDWIN0MD_OFF0;
977
978                 switch (lconfig->pixfmt) {
979                 case PIXFMT_1BPP:
980                         bmw = 0;
981                         break;
982                 case PIXFMT_2BPP:
983                         bmw = 1;
984                         break;
985                 case PIXFMT_4BPP:
986                         bmw = 2;
987                         break;
988                 case PIXFMT_8BPP:
989                         bmw = 3;
990                         break;
991                 default:
992                         break;
993                 }
994                 winmd |= (bmw << OSD_OSDWIN0MD_BMW0_SHIFT);
995
996                 if (lconfig->interlaced)
997                         winmd |= OSD_OSDWIN0MD_OFF0;
998
999                 osd_modify(sd, winmd_mask, winmd, OSD_OSDWIN0MD);
1000                 osd_write(sd, lconfig->line_length >> 5, OSD_OSDWIN0OFST);
1001                 osd_write(sd, lconfig->xpos, OSD_OSDWIN0XP);
1002                 osd_write(sd, lconfig->xsize, OSD_OSDWIN0XL);
1003                 if (lconfig->interlaced) {
1004                         osd_write(sd, lconfig->ypos >> 1, OSD_OSDWIN0YP);
1005                         osd_write(sd, lconfig->ysize >> 1, OSD_OSDWIN0YL);
1006                 } else {
1007                         osd_write(sd, lconfig->ypos, OSD_OSDWIN0YP);
1008                         osd_write(sd, lconfig->ysize, OSD_OSDWIN0YL);
1009                 }
1010                 break;
1011         case WIN_VID0:
1012                 winmd_mask |= OSD_VIDWINMD_VFF0;
1013                 if (lconfig->interlaced)
1014                         winmd |= OSD_VIDWINMD_VFF0;
1015
1016                 osd_modify(sd, winmd_mask, winmd, OSD_VIDWINMD);
1017                 osd_write(sd, lconfig->line_length >> 5, OSD_VIDWIN0OFST);
1018                 osd_write(sd, lconfig->xpos, OSD_VIDWIN0XP);
1019                 osd_write(sd, lconfig->xsize, OSD_VIDWIN0XL);
1020                 /*
1021                  * For YUV420P format the register contents are
1022                  * duplicated in both VID registers
1023                  */
1024                 if ((sd->vpbe_type == VPBE_VERSION_2) &&
1025                                 (lconfig->pixfmt == PIXFMT_NV12)) {
1026                         /* other window also */
1027                         if (lconfig->interlaced) {
1028                                 winmd_mask |= OSD_VIDWINMD_VFF1;
1029                                 winmd |= OSD_VIDWINMD_VFF1;
1030                                 osd_modify(sd, winmd_mask, winmd,
1031                                           OSD_VIDWINMD);
1032                         }
1033
1034                         osd_modify(sd, OSD_MISCCTL_S420D,
1035                                     OSD_MISCCTL_S420D, OSD_MISCCTL);
1036                         osd_write(sd, lconfig->line_length >> 5,
1037                                   OSD_VIDWIN1OFST);
1038                         osd_write(sd, lconfig->xpos, OSD_VIDWIN1XP);
1039                         osd_write(sd, lconfig->xsize, OSD_VIDWIN1XL);
1040                         /*
1041                           * if NV21 pixfmt and line length not 32B
1042                           * aligned (e.g. NTSC), Need to set window
1043                           * X pixel size to be 32B aligned as well
1044                           */
1045                         if (lconfig->xsize % 32) {
1046                                 osd_write(sd,
1047                                           ((lconfig->xsize + 31) & ~31),
1048                                           OSD_VIDWIN1XL);
1049                                 osd_write(sd,
1050                                           ((lconfig->xsize + 31) & ~31),
1051                                           OSD_VIDWIN0XL);
1052                         }
1053                 } else if ((sd->vpbe_type == VPBE_VERSION_2) &&
1054                                 (lconfig->pixfmt != PIXFMT_NV12)) {
1055                         osd_modify(sd, OSD_MISCCTL_S420D, ~OSD_MISCCTL_S420D,
1056                                                 OSD_MISCCTL);
1057                 }
1058
1059                 if (lconfig->interlaced) {
1060                         osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN0YP);
1061                         osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN0YL);
1062                         if ((sd->vpbe_type == VPBE_VERSION_2) &&
1063                                 lconfig->pixfmt == PIXFMT_NV12) {
1064                                 osd_write(sd, lconfig->ypos >> 1,
1065                                           OSD_VIDWIN1YP);
1066                                 osd_write(sd, lconfig->ysize >> 1,
1067                                           OSD_VIDWIN1YL);
1068                         }
1069                 } else {
1070                         osd_write(sd, lconfig->ypos, OSD_VIDWIN0YP);
1071                         osd_write(sd, lconfig->ysize, OSD_VIDWIN0YL);
1072                         if ((sd->vpbe_type == VPBE_VERSION_2) &&
1073                                 lconfig->pixfmt == PIXFMT_NV12) {
1074                                 osd_write(sd, lconfig->ypos, OSD_VIDWIN1YP);
1075                                 osd_write(sd, lconfig->ysize, OSD_VIDWIN1YL);
1076                         }
1077                 }
1078                 break;
1079         case WIN_OSD1:
1080                 /*
1081                  * The caller must ensure that OSD1 is disabled prior to
1082                  * switching from a normal mode to attribute mode or from
1083                  * attribute mode to a normal mode.
1084                  */
1085                 if (lconfig->pixfmt == PIXFMT_OSD_ATTR) {
1086                         if (sd->vpbe_type == VPBE_VERSION_1) {
1087                                 winmd_mask |= OSD_OSDWIN1MD_ATN1E |
1088                                 OSD_OSDWIN1MD_RGB1E | OSD_OSDWIN1MD_CLUTS1 |
1089                                 OSD_OSDWIN1MD_BLND1 | OSD_OSDWIN1MD_TE1;
1090                         } else {
1091                                 winmd_mask |= OSD_OSDWIN1MD_BMP1MD |
1092                                 OSD_OSDWIN1MD_CLUTS1 | OSD_OSDWIN1MD_BLND1 |
1093                                 OSD_OSDWIN1MD_TE1;
1094                         }
1095                 } else {
1096                         if (sd->vpbe_type == VPBE_VERSION_1) {
1097                                 winmd_mask |= OSD_OSDWIN1MD_RGB1E;
1098                                 if (lconfig->pixfmt == PIXFMT_RGB565)
1099                                         winmd |= OSD_OSDWIN1MD_RGB1E;
1100                         } else if ((sd->vpbe_type == VPBE_VERSION_3)
1101                                    || (sd->vpbe_type == VPBE_VERSION_2)) {
1102                                 winmd_mask |= OSD_OSDWIN1MD_BMP1MD;
1103                                 switch (lconfig->pixfmt) {
1104                                 case PIXFMT_RGB565:
1105                                         winmd |=
1106                                             (1 << OSD_OSDWIN1MD_BMP1MD_SHIFT);
1107                                         break;
1108                                 case PIXFMT_RGB888:
1109                                         winmd |=
1110                                             (2 << OSD_OSDWIN1MD_BMP1MD_SHIFT);
1111                                         _osd_enable_rgb888_pixblend(sd,
1112                                                         OSDWIN_OSD1);
1113                                         break;
1114                                 case PIXFMT_YCbCrI:
1115                                 case PIXFMT_YCrCbI:
1116                                         winmd |=
1117                                             (3 << OSD_OSDWIN1MD_BMP1MD_SHIFT);
1118                                         break;
1119                                 default:
1120                                         break;
1121                                 }
1122                         }
1123
1124                         winmd_mask |= OSD_OSDWIN1MD_BMW1;
1125                         switch (lconfig->pixfmt) {
1126                         case PIXFMT_1BPP:
1127                                 bmw = 0;
1128                                 break;
1129                         case PIXFMT_2BPP:
1130                                 bmw = 1;
1131                                 break;
1132                         case PIXFMT_4BPP:
1133                                 bmw = 2;
1134                                 break;
1135                         case PIXFMT_8BPP:
1136                                 bmw = 3;
1137                                 break;
1138                         default:
1139                                 break;
1140                         }
1141                         winmd |= (bmw << OSD_OSDWIN1MD_BMW1_SHIFT);
1142                 }
1143
1144                 winmd_mask |= OSD_OSDWIN1MD_OFF1;
1145                 if (lconfig->interlaced)
1146                         winmd |= OSD_OSDWIN1MD_OFF1;
1147
1148                 osd_modify(sd, winmd_mask, winmd, OSD_OSDWIN1MD);
1149                 osd_write(sd, lconfig->line_length >> 5, OSD_OSDWIN1OFST);
1150                 osd_write(sd, lconfig->xpos, OSD_OSDWIN1XP);
1151                 osd_write(sd, lconfig->xsize, OSD_OSDWIN1XL);
1152                 if (lconfig->interlaced) {
1153                         osd_write(sd, lconfig->ypos >> 1, OSD_OSDWIN1YP);
1154                         osd_write(sd, lconfig->ysize >> 1, OSD_OSDWIN1YL);
1155                 } else {
1156                         osd_write(sd, lconfig->ypos, OSD_OSDWIN1YP);
1157                         osd_write(sd, lconfig->ysize, OSD_OSDWIN1YL);
1158                 }
1159                 break;
1160         case WIN_VID1:
1161                 winmd_mask |= OSD_VIDWINMD_VFF1;
1162                 if (lconfig->interlaced)
1163                         winmd |= OSD_VIDWINMD_VFF1;
1164
1165                 osd_modify(sd, winmd_mask, winmd, OSD_VIDWINMD);
1166                 osd_write(sd, lconfig->line_length >> 5, OSD_VIDWIN1OFST);
1167                 osd_write(sd, lconfig->xpos, OSD_VIDWIN1XP);
1168                 osd_write(sd, lconfig->xsize, OSD_VIDWIN1XL);
1169                 /*
1170                  * For YUV420P format the register contents are
1171                  * duplicated in both VID registers
1172                  */
1173                 if (sd->vpbe_type == VPBE_VERSION_2) {
1174                         if (lconfig->pixfmt == PIXFMT_NV12) {
1175                                 /* other window also */
1176                                 if (lconfig->interlaced) {
1177                                         winmd_mask |= OSD_VIDWINMD_VFF0;
1178                                         winmd |= OSD_VIDWINMD_VFF0;
1179                                         osd_modify(sd, winmd_mask, winmd,
1180                                                   OSD_VIDWINMD);
1181                                 }
1182                                 osd_modify(sd, OSD_MISCCTL_S420D,
1183                                            OSD_MISCCTL_S420D, OSD_MISCCTL);
1184                                 osd_write(sd, lconfig->line_length >> 5,
1185                                           OSD_VIDWIN0OFST);
1186                                 osd_write(sd, lconfig->xpos, OSD_VIDWIN0XP);
1187                                 osd_write(sd, lconfig->xsize, OSD_VIDWIN0XL);
1188                         } else {
1189                                 osd_modify(sd, OSD_MISCCTL_S420D,
1190                                            ~OSD_MISCCTL_S420D, OSD_MISCCTL);
1191                         }
1192                 }
1193
1194                 if (lconfig->interlaced) {
1195                         osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN1YP);
1196                         osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN1YL);
1197                         if ((sd->vpbe_type == VPBE_VERSION_2) &&
1198                                 lconfig->pixfmt == PIXFMT_NV12) {
1199                                 osd_write(sd, lconfig->ypos >> 1,
1200                                           OSD_VIDWIN0YP);
1201                                 osd_write(sd, lconfig->ysize >> 1,
1202                                           OSD_VIDWIN0YL);
1203                         }
1204                 } else {
1205                         osd_write(sd, lconfig->ypos, OSD_VIDWIN1YP);
1206                         osd_write(sd, lconfig->ysize, OSD_VIDWIN1YL);
1207                         if ((sd->vpbe_type == VPBE_VERSION_2) &&
1208                                 lconfig->pixfmt == PIXFMT_NV12) {
1209                                 osd_write(sd, lconfig->ypos, OSD_VIDWIN0YP);
1210                                 osd_write(sd, lconfig->ysize, OSD_VIDWIN0YL);
1211                         }
1212                 }
1213                 break;
1214         }
1215 }
1216
1217 static int osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
1218                                 struct osd_layer_config *lconfig)
1219 {
1220         struct osd_state *osd = sd;
1221         struct osd_window_state *win = &osd->win[layer];
1222         struct osd_layer_config *cfg = &win->lconfig;
1223         unsigned long flags;
1224         int reject_config;
1225
1226         spin_lock_irqsave(&osd->lock, flags);
1227
1228         reject_config = try_layer_config(sd, layer, lconfig);
1229         if (reject_config) {
1230                 spin_unlock_irqrestore(&osd->lock, flags);
1231                 return reject_config;
1232         }
1233
1234         /* update the current Cb/Cr order */
1235         if (is_yc_pixfmt(lconfig->pixfmt))
1236                 osd->yc_pixfmt = lconfig->pixfmt;
1237
1238         /*
1239          * If we are switching OSD1 from normal mode to attribute mode or from
1240          * attribute mode to normal mode, then we must disable the window.
1241          */
1242         if (layer == WIN_OSD1) {
1243                 if (((lconfig->pixfmt == PIXFMT_OSD_ATTR) &&
1244                   (cfg->pixfmt != PIXFMT_OSD_ATTR)) ||
1245                   ((lconfig->pixfmt != PIXFMT_OSD_ATTR) &&
1246                   (cfg->pixfmt == PIXFMT_OSD_ATTR))) {
1247                         win->is_enabled = 0;
1248                         _osd_disable_layer(sd, layer);
1249                 }
1250         }
1251
1252         _osd_set_layer_config(sd, layer, lconfig);
1253
1254         if (layer == WIN_OSD1) {
1255                 struct osd_osdwin_state *osdwin_state =
1256                     &osd->osdwin[OSDWIN_OSD1];
1257
1258                 if ((lconfig->pixfmt != PIXFMT_OSD_ATTR) &&
1259                   (cfg->pixfmt == PIXFMT_OSD_ATTR)) {
1260                         /*
1261                          * We just switched OSD1 from attribute mode to normal
1262                          * mode, so we must initialize the CLUT select, the
1263                          * blend factor, transparency colorkey enable, and
1264                          * attenuation enable (DM6446 only) bits in the
1265                          * OSDWIN1MD register.
1266                          */
1267                         _osd_set_osd_clut(sd, OSDWIN_OSD1,
1268                                                    osdwin_state->clut);
1269                         _osd_set_blending_factor(sd, OSDWIN_OSD1,
1270                                                           osdwin_state->blend);
1271                         if (osdwin_state->colorkey_blending) {
1272                                 _osd_enable_color_key(sd, OSDWIN_OSD1,
1273                                                                osdwin_state->
1274                                                                colorkey,
1275                                                                lconfig->pixfmt);
1276                         } else
1277                                 _osd_disable_color_key(sd, OSDWIN_OSD1);
1278                         _osd_set_rec601_attenuation(sd, OSDWIN_OSD1,
1279                                                     osdwin_state->
1280                                                     rec601_attenuation);
1281                 } else if ((lconfig->pixfmt == PIXFMT_OSD_ATTR) &&
1282                   (cfg->pixfmt != PIXFMT_OSD_ATTR)) {
1283                         /*
1284                          * We just switched OSD1 from normal mode to attribute
1285                          * mode, so we must initialize the blink enable and
1286                          * blink interval bits in the OSDATRMD register.
1287                          */
1288                         _osd_set_blink_attribute(sd, osd->is_blinking,
1289                                                           osd->blink);
1290                 }
1291         }
1292
1293         /*
1294          * If we just switched to a 1-, 2-, or 4-bits-per-pixel bitmap format
1295          * then configure a default palette map.
1296          */
1297         if ((lconfig->pixfmt != cfg->pixfmt) &&
1298           ((lconfig->pixfmt == PIXFMT_1BPP) ||
1299           (lconfig->pixfmt == PIXFMT_2BPP) ||
1300           (lconfig->pixfmt == PIXFMT_4BPP))) {
1301                 enum osd_win_layer osdwin =
1302                     ((layer == WIN_OSD0) ? OSDWIN_OSD0 : OSDWIN_OSD1);
1303                 struct osd_osdwin_state *osdwin_state =
1304                     &osd->osdwin[osdwin];
1305                 unsigned char clut_index;
1306                 unsigned char clut_entries = 0;
1307
1308                 switch (lconfig->pixfmt) {
1309                 case PIXFMT_1BPP:
1310                         clut_entries = 2;
1311                         break;
1312                 case PIXFMT_2BPP:
1313                         clut_entries = 4;
1314                         break;
1315                 case PIXFMT_4BPP:
1316                         clut_entries = 16;
1317                         break;
1318                 default:
1319                         break;
1320                 }
1321                 /*
1322                  * The default palette map maps the pixel value to the clut
1323                  * index, i.e. pixel value 0 maps to clut entry 0, pixel value
1324                  * 1 maps to clut entry 1, etc.
1325                  */
1326                 for (clut_index = 0; clut_index < 16; clut_index++) {
1327                         osdwin_state->palette_map[clut_index] = clut_index;
1328                         if (clut_index < clut_entries) {
1329                                 _osd_set_palette_map(sd, osdwin, clut_index,
1330                                                      clut_index,
1331                                                      lconfig->pixfmt);
1332                         }
1333                 }
1334         }
1335
1336         *cfg = *lconfig;
1337         /* DM6446: configure the RGB888 enable and window selection */
1338         if (osd->win[WIN_VID0].lconfig.pixfmt == PIXFMT_RGB888)
1339                 _osd_enable_vid_rgb888(sd, WIN_VID0);
1340         else if (osd->win[WIN_VID1].lconfig.pixfmt == PIXFMT_RGB888)
1341                 _osd_enable_vid_rgb888(sd, WIN_VID1);
1342         else
1343                 _osd_disable_vid_rgb888(sd);
1344
1345         if (layer == WIN_VID0) {
1346                 osd->pingpong =
1347                     _osd_dm6446_vid0_pingpong(sd, osd->field_inversion,
1348                                                        win->fb_base_phys,
1349                                                        cfg);
1350         }
1351
1352         spin_unlock_irqrestore(&osd->lock, flags);
1353
1354         return 0;
1355 }
1356
1357 static void osd_init_layer(struct osd_state *sd, enum osd_layer layer)
1358 {
1359         struct osd_state *osd = sd;
1360         struct osd_window_state *win = &osd->win[layer];
1361         enum osd_win_layer osdwin;
1362         struct osd_osdwin_state *osdwin_state;
1363         struct osd_layer_config *cfg = &win->lconfig;
1364         unsigned long flags;
1365
1366         spin_lock_irqsave(&osd->lock, flags);
1367
1368         win->is_enabled = 0;
1369         _osd_disable_layer(sd, layer);
1370
1371         win->h_zoom = ZOOM_X1;
1372         win->v_zoom = ZOOM_X1;
1373         _osd_set_zoom(sd, layer, win->h_zoom, win->v_zoom);
1374
1375         win->fb_base_phys = 0;
1376         _osd_start_layer(sd, layer, win->fb_base_phys, 0);
1377
1378         cfg->line_length = 0;
1379         cfg->xsize = 0;
1380         cfg->ysize = 0;
1381         cfg->xpos = 0;
1382         cfg->ypos = 0;
1383         cfg->interlaced = 0;
1384         switch (layer) {
1385         case WIN_OSD0:
1386         case WIN_OSD1:
1387                 osdwin = (layer == WIN_OSD0) ? OSDWIN_OSD0 : OSDWIN_OSD1;
1388                 osdwin_state = &osd->osdwin[osdwin];
1389                 /*
1390                  * Other code relies on the fact that OSD windows default to a
1391                  * bitmap pixel format when they are deallocated, so don't
1392                  * change this default pixel format.
1393                  */
1394                 cfg->pixfmt = PIXFMT_8BPP;
1395                 _osd_set_layer_config(sd, layer, cfg);
1396                 osdwin_state->clut = RAM_CLUT;
1397                 _osd_set_osd_clut(sd, osdwin, osdwin_state->clut);
1398                 osdwin_state->colorkey_blending = 0;
1399                 _osd_disable_color_key(sd, osdwin);
1400                 osdwin_state->blend = OSD_8_VID_0;
1401                 _osd_set_blending_factor(sd, osdwin, osdwin_state->blend);
1402                 osdwin_state->rec601_attenuation = 0;
1403                 _osd_set_rec601_attenuation(sd, osdwin,
1404                                                      osdwin_state->
1405                                                      rec601_attenuation);
1406                 if (osdwin == OSDWIN_OSD1) {
1407                         osd->is_blinking = 0;
1408                         osd->blink = BLINK_X1;
1409                 }
1410                 break;
1411         case WIN_VID0:
1412         case WIN_VID1:
1413                 cfg->pixfmt = osd->yc_pixfmt;
1414                 _osd_set_layer_config(sd, layer, cfg);
1415                 break;
1416         }
1417
1418         spin_unlock_irqrestore(&osd->lock, flags);
1419 }
1420
1421 static void osd_release_layer(struct osd_state *sd, enum osd_layer layer)
1422 {
1423         struct osd_state *osd = sd;
1424         struct osd_window_state *win = &osd->win[layer];
1425         unsigned long flags;
1426
1427         spin_lock_irqsave(&osd->lock, flags);
1428
1429         if (!win->is_allocated) {
1430                 spin_unlock_irqrestore(&osd->lock, flags);
1431                 return;
1432         }
1433
1434         spin_unlock_irqrestore(&osd->lock, flags);
1435         osd_init_layer(sd, layer);
1436         spin_lock_irqsave(&osd->lock, flags);
1437
1438         win->is_allocated = 0;
1439
1440         spin_unlock_irqrestore(&osd->lock, flags);
1441 }
1442
1443 static int osd_request_layer(struct osd_state *sd, enum osd_layer layer)
1444 {
1445         struct osd_state *osd = sd;
1446         struct osd_window_state *win = &osd->win[layer];
1447         unsigned long flags;
1448
1449         spin_lock_irqsave(&osd->lock, flags);
1450
1451         if (win->is_allocated) {
1452                 spin_unlock_irqrestore(&osd->lock, flags);
1453                 return -1;
1454         }
1455         win->is_allocated = 1;
1456
1457         spin_unlock_irqrestore(&osd->lock, flags);
1458
1459         return 0;
1460 }
1461
1462 static void _osd_init(struct osd_state *sd)
1463 {
1464         osd_write(sd, 0, OSD_MODE);
1465         osd_write(sd, 0, OSD_VIDWINMD);
1466         osd_write(sd, 0, OSD_OSDWIN0MD);
1467         osd_write(sd, 0, OSD_OSDWIN1MD);
1468         osd_write(sd, 0, OSD_RECTCUR);
1469         osd_write(sd, 0, OSD_MISCCTL);
1470         if (sd->vpbe_type == VPBE_VERSION_3) {
1471                 osd_write(sd, 0, OSD_VBNDRY);
1472                 osd_write(sd, 0, OSD_EXTMODE);
1473                 osd_write(sd, OSD_MISCCTL_DMANG, OSD_MISCCTL);
1474         }
1475 }
1476
1477 static void osd_set_left_margin(struct osd_state *sd, u32 val)
1478 {
1479         osd_write(sd, val, OSD_BASEPX);
1480 }
1481
1482 static void osd_set_top_margin(struct osd_state *sd, u32 val)
1483 {
1484         osd_write(sd, val, OSD_BASEPY);
1485 }
1486
1487 static int osd_initialize(struct osd_state *osd)
1488 {
1489         if (osd == NULL)
1490                 return -ENODEV;
1491         _osd_init(osd);
1492
1493         /* set default Cb/Cr order */
1494         osd->yc_pixfmt = PIXFMT_YCbCrI;
1495
1496         if (osd->vpbe_type == VPBE_VERSION_3) {
1497                 /*
1498                  * ROM CLUT1 on the DM355 is similar (identical?) to ROM CLUT0
1499                  * on the DM6446, so make ROM_CLUT1 the default on the DM355.
1500                  */
1501                 osd->rom_clut = ROM_CLUT1;
1502         }
1503
1504         _osd_set_field_inversion(osd, osd->field_inversion);
1505         _osd_set_rom_clut(osd, osd->rom_clut);
1506
1507         osd_init_layer(osd, WIN_OSD0);
1508         osd_init_layer(osd, WIN_VID0);
1509         osd_init_layer(osd, WIN_OSD1);
1510         osd_init_layer(osd, WIN_VID1);
1511
1512         return 0;
1513 }
1514
1515 static const struct vpbe_osd_ops osd_ops = {
1516         .initialize = osd_initialize,
1517         .request_layer = osd_request_layer,
1518         .release_layer = osd_release_layer,
1519         .enable_layer = osd_enable_layer,
1520         .disable_layer = osd_disable_layer,
1521         .set_layer_config = osd_set_layer_config,
1522         .get_layer_config = osd_get_layer_config,
1523         .start_layer = osd_start_layer,
1524         .set_left_margin = osd_set_left_margin,
1525         .set_top_margin = osd_set_top_margin,
1526 };
1527
1528 static int osd_probe(struct platform_device *pdev)
1529 {
1530         struct osd_platform_data *pdata;
1531         struct osd_state *osd;
1532         struct resource *res;
1533         int ret = 0;
1534
1535         osd = kzalloc(sizeof(struct osd_state), GFP_KERNEL);
1536         if (osd == NULL)
1537                 return -ENOMEM;
1538
1539         osd->dev = &pdev->dev;
1540         pdata = (struct osd_platform_data *)pdev->dev.platform_data;
1541         osd->vpbe_type = (enum vpbe_version)pdata->vpbe_type;
1542         if (NULL == pdev->dev.platform_data) {
1543                 dev_err(osd->dev, "No platform data defined for OSD"
1544                         " sub device\n");
1545                 ret = -ENOENT;
1546                 goto free_mem;
1547         }
1548
1549         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1550         if (!res) {
1551                 dev_err(osd->dev, "Unable to get OSD register address map\n");
1552                 ret = -ENODEV;
1553                 goto free_mem;
1554         }
1555         osd->osd_base_phys = res->start;
1556         osd->osd_size = resource_size(res);
1557         if (!request_mem_region(osd->osd_base_phys, osd->osd_size,
1558                                 MODULE_NAME)) {
1559                 dev_err(osd->dev, "Unable to reserve OSD MMIO region\n");
1560                 ret = -ENODEV;
1561                 goto free_mem;
1562         }
1563         osd->osd_base = (unsigned long)ioremap_nocache(res->start,
1564                                                         osd->osd_size);
1565         if (!osd->osd_base) {
1566                 dev_err(osd->dev, "Unable to map the OSD region\n");
1567                 ret = -ENODEV;
1568                 goto release_mem_region;
1569         }
1570         spin_lock_init(&osd->lock);
1571         osd->ops = osd_ops;
1572         platform_set_drvdata(pdev, osd);
1573         dev_notice(osd->dev, "OSD sub device probe success\n");
1574         return ret;
1575
1576 release_mem_region:
1577         release_mem_region(osd->osd_base_phys, osd->osd_size);
1578 free_mem:
1579         kfree(osd);
1580         return ret;
1581 }
1582
1583 static int osd_remove(struct platform_device *pdev)
1584 {
1585         struct osd_state *osd = platform_get_drvdata(pdev);
1586
1587         iounmap((void *)osd->osd_base);
1588         release_mem_region(osd->osd_base_phys, osd->osd_size);
1589         kfree(osd);
1590         return 0;
1591 }
1592
1593 static struct platform_driver osd_driver = {
1594         .probe          = osd_probe,
1595         .remove         = osd_remove,
1596         .driver         = {
1597                 .name   = MODULE_NAME,
1598                 .owner  = THIS_MODULE,
1599         },
1600 };
1601
1602 module_platform_driver(osd_driver);
1603
1604 MODULE_LICENSE("GPL");
1605 MODULE_DESCRIPTION("DaVinci OSD Manager Driver");
1606 MODULE_AUTHOR("Texas Instruments");