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