[media] davinci vpbe: OSD(On Screen Display) block
[linux-2.6.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                 break;
252         case OSDWIN_OSD1:
253                 osd_modify(sd, OSD_OSDWIN1MD_ATN1E,
254                           enable ? OSD_OSDWIN1MD_ATN1E : 0,
255                           OSD_OSDWIN1MD);
256                 break;
257         }
258 }
259
260 static void _osd_set_blending_factor(struct osd_state *sd,
261                                      enum osd_win_layer osdwin,
262                                      enum osd_blending_factor blend)
263 {
264         switch (osdwin) {
265         case OSDWIN_OSD0:
266                 osd_modify(sd, OSD_OSDWIN0MD_BLND0,
267                           blend << OSD_OSDWIN0MD_BLND0_SHIFT, OSD_OSDWIN0MD);
268                 break;
269         case OSDWIN_OSD1:
270                 osd_modify(sd, OSD_OSDWIN1MD_BLND1,
271                           blend << OSD_OSDWIN1MD_BLND1_SHIFT, OSD_OSDWIN1MD);
272                 break;
273         }
274 }
275
276 static void _osd_enable_color_key(struct osd_state *sd,
277                                   enum osd_win_layer osdwin,
278                                   unsigned colorkey,
279                                   enum osd_pix_format pixfmt)
280 {
281         switch (pixfmt) {
282         case PIXFMT_RGB565:
283                 osd_write(sd, colorkey & OSD_TRANSPVAL_RGBTRANS,
284                           OSD_TRANSPVAL);
285                 break;
286         default:
287                 break;
288         }
289
290         switch (osdwin) {
291         case OSDWIN_OSD0:
292                 osd_set(sd, OSD_OSDWIN0MD_TE0, OSD_OSDWIN0MD);
293                 break;
294         case OSDWIN_OSD1:
295                 osd_set(sd, OSD_OSDWIN1MD_TE1, OSD_OSDWIN1MD);
296                 break;
297         }
298 }
299
300 static void _osd_disable_color_key(struct osd_state *sd,
301                                    enum osd_win_layer osdwin)
302 {
303         switch (osdwin) {
304         case OSDWIN_OSD0:
305                 osd_clear(sd, OSD_OSDWIN0MD_TE0, OSD_OSDWIN0MD);
306                 break;
307         case OSDWIN_OSD1:
308                 osd_clear(sd, OSD_OSDWIN1MD_TE1, OSD_OSDWIN1MD);
309                 break;
310         }
311 }
312
313 static void _osd_set_osd_clut(struct osd_state *sd,
314                               enum osd_win_layer osdwin,
315                               enum osd_clut clut)
316 {
317         u32 winmd = 0;
318
319         switch (osdwin) {
320         case OSDWIN_OSD0:
321                 if (clut == RAM_CLUT)
322                         winmd |= OSD_OSDWIN0MD_CLUTS0;
323                 osd_modify(sd, OSD_OSDWIN0MD_CLUTS0, winmd, OSD_OSDWIN0MD);
324                 break;
325         case OSDWIN_OSD1:
326                 if (clut == RAM_CLUT)
327                         winmd |= OSD_OSDWIN1MD_CLUTS1;
328                 osd_modify(sd, OSD_OSDWIN1MD_CLUTS1, winmd, OSD_OSDWIN1MD);
329                 break;
330         }
331 }
332
333 static void _osd_set_zoom(struct osd_state *sd, enum osd_layer layer,
334                           enum osd_zoom_factor h_zoom,
335                           enum osd_zoom_factor v_zoom)
336 {
337         u32 winmd = 0;
338
339         switch (layer) {
340         case WIN_OSD0:
341                 winmd |= (h_zoom << OSD_OSDWIN0MD_OHZ0_SHIFT);
342                 winmd |= (v_zoom << OSD_OSDWIN0MD_OVZ0_SHIFT);
343                 osd_modify(sd, OSD_OSDWIN0MD_OHZ0 | OSD_OSDWIN0MD_OVZ0, winmd,
344                           OSD_OSDWIN0MD);
345                 break;
346         case WIN_VID0:
347                 winmd |= (h_zoom << OSD_VIDWINMD_VHZ0_SHIFT);
348                 winmd |= (v_zoom << OSD_VIDWINMD_VVZ0_SHIFT);
349                 osd_modify(sd, OSD_VIDWINMD_VHZ0 | OSD_VIDWINMD_VVZ0, winmd,
350                           OSD_VIDWINMD);
351                 break;
352         case WIN_OSD1:
353                 winmd |= (h_zoom << OSD_OSDWIN1MD_OHZ1_SHIFT);
354                 winmd |= (v_zoom << OSD_OSDWIN1MD_OVZ1_SHIFT);
355                 osd_modify(sd, OSD_OSDWIN1MD_OHZ1 | OSD_OSDWIN1MD_OVZ1, winmd,
356                           OSD_OSDWIN1MD);
357                 break;
358         case WIN_VID1:
359                 winmd |= (h_zoom << OSD_VIDWINMD_VHZ1_SHIFT);
360                 winmd |= (v_zoom << OSD_VIDWINMD_VVZ1_SHIFT);
361                 osd_modify(sd, OSD_VIDWINMD_VHZ1 | OSD_VIDWINMD_VVZ1, winmd,
362                           OSD_VIDWINMD);
363                 break;
364         }
365 }
366
367 static void _osd_disable_layer(struct osd_state *sd, enum osd_layer layer)
368 {
369         switch (layer) {
370         case WIN_OSD0:
371                 osd_clear(sd, OSD_OSDWIN0MD_OACT0, OSD_OSDWIN0MD);
372                 break;
373         case WIN_VID0:
374                 osd_clear(sd, OSD_VIDWINMD_ACT0, OSD_VIDWINMD);
375                 break;
376         case WIN_OSD1:
377                 /* disable attribute mode as well as disabling the window */
378                 osd_clear(sd, OSD_OSDWIN1MD_OASW | OSD_OSDWIN1MD_OACT1,
379                           OSD_OSDWIN1MD);
380                 break;
381         case WIN_VID1:
382                 osd_clear(sd, OSD_VIDWINMD_ACT1, OSD_VIDWINMD);
383                 break;
384         }
385 }
386
387 static void osd_disable_layer(struct osd_state *sd, enum osd_layer layer)
388 {
389         struct osd_state *osd = sd;
390         struct osd_window_state *win = &osd->win[layer];
391         unsigned long flags;
392
393         spin_lock_irqsave(&osd->lock, flags);
394
395         if (!win->is_enabled) {
396                 spin_unlock_irqrestore(&osd->lock, flags);
397                 return;
398         }
399         win->is_enabled = 0;
400
401         _osd_disable_layer(sd, layer);
402
403         spin_unlock_irqrestore(&osd->lock, flags);
404 }
405
406 static void _osd_enable_attribute_mode(struct osd_state *sd)
407 {
408         /* enable attribute mode for OSD1 */
409         osd_set(sd, OSD_OSDWIN1MD_OASW, OSD_OSDWIN1MD);
410 }
411
412 static void _osd_enable_layer(struct osd_state *sd, enum osd_layer layer)
413 {
414         switch (layer) {
415         case WIN_OSD0:
416                 osd_set(sd, OSD_OSDWIN0MD_OACT0, OSD_OSDWIN0MD);
417                 break;
418         case WIN_VID0:
419                 osd_set(sd, OSD_VIDWINMD_ACT0, OSD_VIDWINMD);
420                 break;
421         case WIN_OSD1:
422                 /* enable OSD1 and disable attribute mode */
423                 osd_modify(sd, OSD_OSDWIN1MD_OASW | OSD_OSDWIN1MD_OACT1,
424                           OSD_OSDWIN1MD_OACT1, OSD_OSDWIN1MD);
425                 break;
426         case WIN_VID1:
427                 osd_set(sd, OSD_VIDWINMD_ACT1, OSD_VIDWINMD);
428                 break;
429         }
430 }
431
432 static int osd_enable_layer(struct osd_state *sd, enum osd_layer layer,
433                             int otherwin)
434 {
435         struct osd_state *osd = sd;
436         struct osd_window_state *win = &osd->win[layer];
437         struct osd_layer_config *cfg = &win->lconfig;
438         unsigned long flags;
439
440         spin_lock_irqsave(&osd->lock, flags);
441
442         /*
443          * use otherwin flag to know this is the other vid window
444          * in YUV420 mode, if is, skip this check
445          */
446         if (!otherwin && (!win->is_allocated ||
447                         !win->fb_base_phys ||
448                         !cfg->line_length ||
449                         !cfg->xsize ||
450                         !cfg->ysize)) {
451                 spin_unlock_irqrestore(&osd->lock, flags);
452                 return -1;
453         }
454
455         if (win->is_enabled) {
456                 spin_unlock_irqrestore(&osd->lock, flags);
457                 return 0;
458         }
459         win->is_enabled = 1;
460
461         if (cfg->pixfmt != PIXFMT_OSD_ATTR)
462                 _osd_enable_layer(sd, layer);
463         else {
464                 _osd_enable_attribute_mode(sd);
465                 _osd_set_blink_attribute(sd, osd->is_blinking, osd->blink);
466         }
467
468         spin_unlock_irqrestore(&osd->lock, flags);
469
470         return 0;
471 }
472
473 static void _osd_start_layer(struct osd_state *sd, enum osd_layer layer,
474                              unsigned long fb_base_phys,
475                              unsigned long cbcr_ofst)
476 {
477         switch (layer) {
478         case WIN_OSD0:
479                 osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN0ADR);
480                 break;
481         case WIN_VID0:
482                 osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR);
483                 break;
484         case WIN_OSD1:
485                 osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN1ADR);
486                 break;
487         case WIN_VID1:
488                 osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN1ADR);
489                 break;
490         }
491 }
492
493 static void osd_start_layer(struct osd_state *sd, enum osd_layer layer,
494                             unsigned long fb_base_phys,
495                             unsigned long cbcr_ofst)
496 {
497         struct osd_state *osd = sd;
498         struct osd_window_state *win = &osd->win[layer];
499         struct osd_layer_config *cfg = &win->lconfig;
500         unsigned long flags;
501
502         spin_lock_irqsave(&osd->lock, flags);
503
504         win->fb_base_phys = fb_base_phys & ~0x1F;
505         _osd_start_layer(sd, layer, fb_base_phys, cbcr_ofst);
506
507         if (layer == WIN_VID0) {
508                 osd->pingpong =
509                     _osd_dm6446_vid0_pingpong(sd, osd->field_inversion,
510                                                        win->fb_base_phys,
511                                                        cfg);
512         }
513
514         spin_unlock_irqrestore(&osd->lock, flags);
515 }
516
517 static void osd_get_layer_config(struct osd_state *sd, enum osd_layer layer,
518                                  struct osd_layer_config *lconfig)
519 {
520         struct osd_state *osd = sd;
521         struct osd_window_state *win = &osd->win[layer];
522         unsigned long flags;
523
524         spin_lock_irqsave(&osd->lock, flags);
525
526         *lconfig = win->lconfig;
527
528         spin_unlock_irqrestore(&osd->lock, flags);
529 }
530
531 /**
532  * try_layer_config() - Try a specific configuration for the layer
533  * @sd  - ptr to struct osd_state
534  * @layer - layer to configure
535  * @lconfig - layer configuration to try
536  *
537  * If the requested lconfig is completely rejected and the value of lconfig on
538  * exit is the current lconfig, then try_layer_config() returns 1.  Otherwise,
539  * try_layer_config() returns 0.  A return value of 0 does not necessarily mean
540  * that the value of lconfig on exit is identical to the value of lconfig on
541  * entry, but merely that it represents a change from the current lconfig.
542  */
543 static int try_layer_config(struct osd_state *sd, enum osd_layer layer,
544                             struct osd_layer_config *lconfig)
545 {
546         struct osd_state *osd = sd;
547         struct osd_window_state *win = &osd->win[layer];
548         int bad_config;
549
550         /* verify that the pixel format is compatible with the layer */
551         switch (lconfig->pixfmt) {
552         case PIXFMT_1BPP:
553         case PIXFMT_2BPP:
554         case PIXFMT_4BPP:
555         case PIXFMT_8BPP:
556         case PIXFMT_RGB565:
557                 bad_config = !is_osd_win(layer);
558                 break;
559         case PIXFMT_YCbCrI:
560         case PIXFMT_YCrCbI:
561                 bad_config = !is_vid_win(layer);
562                 break;
563         case PIXFMT_RGB888:
564                 bad_config = !is_vid_win(layer);
565                 break;
566         case PIXFMT_NV12:
567                 bad_config = 1;
568                 break;
569         case PIXFMT_OSD_ATTR:
570                 bad_config = (layer != WIN_OSD1);
571                 break;
572         default:
573                 bad_config = 1;
574                 break;
575         }
576         if (bad_config) {
577                 /*
578                  * The requested pixel format is incompatible with the layer,
579                  * so keep the current layer configuration.
580                  */
581                 *lconfig = win->lconfig;
582                 return bad_config;
583         }
584
585         /* DM6446: */
586         /* only one OSD window at a time can use RGB pixel formats */
587         if (is_osd_win(layer) && is_rgb_pixfmt(lconfig->pixfmt)) {
588                 enum osd_pix_format pixfmt;
589                 if (layer == WIN_OSD0)
590                         pixfmt = osd->win[WIN_OSD1].lconfig.pixfmt;
591                 else
592                         pixfmt = osd->win[WIN_OSD0].lconfig.pixfmt;
593
594                 if (is_rgb_pixfmt(pixfmt)) {
595                         /*
596                          * The other OSD window is already configured for an
597                          * RGB, so keep the current layer configuration.
598                          */
599                         *lconfig = win->lconfig;
600                         return 1;
601                 }
602         }
603
604         /* DM6446: only one video window at a time can use RGB888 */
605         if (is_vid_win(layer) && lconfig->pixfmt == PIXFMT_RGB888) {
606                 enum osd_pix_format pixfmt;
607
608                 if (layer == WIN_VID0)
609                         pixfmt = osd->win[WIN_VID1].lconfig.pixfmt;
610                 else
611                         pixfmt = osd->win[WIN_VID0].lconfig.pixfmt;
612
613                 if (pixfmt == PIXFMT_RGB888) {
614                         /*
615                          * The other video window is already configured for
616                          * RGB888, so keep the current layer configuration.
617                          */
618                         *lconfig = win->lconfig;
619                         return 1;
620                 }
621         }
622
623         /* window dimensions must be non-zero */
624         if (!lconfig->line_length || !lconfig->xsize || !lconfig->ysize) {
625                 *lconfig = win->lconfig;
626                 return 1;
627         }
628
629         /* round line_length up to a multiple of 32 */
630         lconfig->line_length = ((lconfig->line_length + 31) / 32) * 32;
631         lconfig->line_length =
632             min(lconfig->line_length, (unsigned)MAX_LINE_LENGTH);
633         lconfig->xsize = min(lconfig->xsize, (unsigned)MAX_WIN_SIZE);
634         lconfig->ysize = min(lconfig->ysize, (unsigned)MAX_WIN_SIZE);
635         lconfig->xpos = min(lconfig->xpos, (unsigned)MAX_WIN_SIZE);
636         lconfig->ypos = min(lconfig->ypos, (unsigned)MAX_WIN_SIZE);
637         lconfig->interlaced = (lconfig->interlaced != 0);
638         if (lconfig->interlaced) {
639                 /* ysize and ypos must be even for interlaced displays */
640                 lconfig->ysize &= ~1;
641                 lconfig->ypos &= ~1;
642         }
643
644         return 0;
645 }
646
647 static void _osd_disable_vid_rgb888(struct osd_state *sd)
648 {
649         /*
650          * The DM6446 supports RGB888 pixel format in a single video window.
651          * This routine disables RGB888 pixel format for both video windows.
652          * The caller must ensure that neither video window is currently
653          * configured for RGB888 pixel format.
654          */
655         osd_clear(sd, OSD_MISCCTL_RGBEN, OSD_MISCCTL);
656 }
657
658 static void _osd_enable_vid_rgb888(struct osd_state *sd,
659                                    enum osd_layer layer)
660 {
661         /*
662          * The DM6446 supports RGB888 pixel format in a single video window.
663          * This routine enables RGB888 pixel format for the specified video
664          * window.  The caller must ensure that the other video window is not
665          * currently configured for RGB888 pixel format, as this routine will
666          * disable RGB888 pixel format for the other window.
667          */
668         if (layer == WIN_VID0) {
669                 osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
670                           OSD_MISCCTL_RGBEN, OSD_MISCCTL);
671         } else if (layer == WIN_VID1) {
672                 osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
673                           OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
674                           OSD_MISCCTL);
675         }
676 }
677
678 static void _osd_set_cbcr_order(struct osd_state *sd,
679                                 enum osd_pix_format pixfmt)
680 {
681         /*
682          * The caller must ensure that all windows using YC pixfmt use the same
683          * Cb/Cr order.
684          */
685         if (pixfmt == PIXFMT_YCbCrI)
686                 osd_clear(sd, OSD_MODE_CS, OSD_MODE);
687         else if (pixfmt == PIXFMT_YCrCbI)
688                 osd_set(sd, OSD_MODE_CS, OSD_MODE);
689 }
690
691 static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
692                                   const struct osd_layer_config *lconfig)
693 {
694         u32 winmd = 0, winmd_mask = 0, bmw = 0;
695
696         _osd_set_cbcr_order(sd, lconfig->pixfmt);
697
698         switch (layer) {
699         case WIN_OSD0:
700                 winmd_mask |= OSD_OSDWIN0MD_RGB0E;
701                 if (lconfig->pixfmt == PIXFMT_RGB565)
702                         winmd |= OSD_OSDWIN0MD_RGB0E;
703
704                 winmd_mask |= OSD_OSDWIN0MD_BMW0 | OSD_OSDWIN0MD_OFF0;
705
706                 switch (lconfig->pixfmt) {
707                 case PIXFMT_1BPP:
708                         bmw = 0;
709                         break;
710                 case PIXFMT_2BPP:
711                         bmw = 1;
712                         break;
713                 case PIXFMT_4BPP:
714                         bmw = 2;
715                         break;
716                 case PIXFMT_8BPP:
717                         bmw = 3;
718                         break;
719                 default:
720                         break;
721                 }
722                 winmd |= (bmw << OSD_OSDWIN0MD_BMW0_SHIFT);
723
724                 if (lconfig->interlaced)
725                         winmd |= OSD_OSDWIN0MD_OFF0;
726
727                 osd_modify(sd, winmd_mask, winmd, OSD_OSDWIN0MD);
728                 osd_write(sd, lconfig->line_length >> 5, OSD_OSDWIN0OFST);
729                 osd_write(sd, lconfig->xpos, OSD_OSDWIN0XP);
730                 osd_write(sd, lconfig->xsize, OSD_OSDWIN0XL);
731                 if (lconfig->interlaced) {
732                         osd_write(sd, lconfig->ypos >> 1, OSD_OSDWIN0YP);
733                         osd_write(sd, lconfig->ysize >> 1, OSD_OSDWIN0YL);
734                 } else {
735                         osd_write(sd, lconfig->ypos, OSD_OSDWIN0YP);
736                         osd_write(sd, lconfig->ysize, OSD_OSDWIN0YL);
737                 }
738                 break;
739         case WIN_VID0:
740                 winmd_mask |= OSD_VIDWINMD_VFF0;
741                 if (lconfig->interlaced)
742                         winmd |= OSD_VIDWINMD_VFF0;
743
744                 osd_modify(sd, winmd_mask, winmd, OSD_VIDWINMD);
745                 osd_write(sd, lconfig->line_length >> 5, OSD_VIDWIN0OFST);
746                 osd_write(sd, lconfig->xpos, OSD_VIDWIN0XP);
747                 osd_write(sd, lconfig->xsize, OSD_VIDWIN0XL);
748                 /*
749                  * For YUV420P format the register contents are
750                  * duplicated in both VID registers
751                  */
752                 if (lconfig->interlaced) {
753                         osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN0YP);
754                         osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN0YL);
755                 } else {
756                         osd_write(sd, lconfig->ypos, OSD_VIDWIN0YP);
757                         osd_write(sd, lconfig->ysize, OSD_VIDWIN0YL);
758                 }
759                 break;
760         case WIN_OSD1:
761                 /*
762                  * The caller must ensure that OSD1 is disabled prior to
763                  * switching from a normal mode to attribute mode or from
764                  * attribute mode to a normal mode.
765                  */
766                 if (lconfig->pixfmt == PIXFMT_OSD_ATTR) {
767                         winmd_mask |=
768                             OSD_OSDWIN1MD_ATN1E | OSD_OSDWIN1MD_RGB1E |
769                             OSD_OSDWIN1MD_CLUTS1 |
770                             OSD_OSDWIN1MD_BLND1 | OSD_OSDWIN1MD_TE1;
771                 } else {
772                         winmd_mask |= OSD_OSDWIN1MD_RGB1E;
773                         if (lconfig->pixfmt == PIXFMT_RGB565)
774                                 winmd |= OSD_OSDWIN1MD_RGB1E;
775
776                         winmd_mask |= OSD_OSDWIN1MD_BMW1;
777                         switch (lconfig->pixfmt) {
778                         case PIXFMT_1BPP:
779                                 bmw = 0;
780                                 break;
781                         case PIXFMT_2BPP:
782                                 bmw = 1;
783                                 break;
784                         case PIXFMT_4BPP:
785                                 bmw = 2;
786                                 break;
787                         case PIXFMT_8BPP:
788                                 bmw = 3;
789                                 break;
790                         default:
791                                 break;
792                         }
793                         winmd |= (bmw << OSD_OSDWIN1MD_BMW1_SHIFT);
794                 }
795
796                 winmd_mask |= OSD_OSDWIN1MD_OFF1;
797                 if (lconfig->interlaced)
798                         winmd |= OSD_OSDWIN1MD_OFF1;
799
800                 osd_modify(sd, winmd_mask, winmd, OSD_OSDWIN1MD);
801                 osd_write(sd, lconfig->line_length >> 5, OSD_OSDWIN1OFST);
802                 osd_write(sd, lconfig->xpos, OSD_OSDWIN1XP);
803                 osd_write(sd, lconfig->xsize, OSD_OSDWIN1XL);
804                 if (lconfig->interlaced) {
805                         osd_write(sd, lconfig->ypos >> 1, OSD_OSDWIN1YP);
806                         osd_write(sd, lconfig->ysize >> 1, OSD_OSDWIN1YL);
807                 } else {
808                         osd_write(sd, lconfig->ypos, OSD_OSDWIN1YP);
809                         osd_write(sd, lconfig->ysize, OSD_OSDWIN1YL);
810                 }
811                 break;
812         case WIN_VID1:
813                 winmd_mask |= OSD_VIDWINMD_VFF1;
814                 if (lconfig->interlaced)
815                         winmd |= OSD_VIDWINMD_VFF1;
816
817                 osd_modify(sd, winmd_mask, winmd, OSD_VIDWINMD);
818                 osd_write(sd, lconfig->line_length >> 5, OSD_VIDWIN1OFST);
819                 osd_write(sd, lconfig->xpos, OSD_VIDWIN1XP);
820                 osd_write(sd, lconfig->xsize, OSD_VIDWIN1XL);
821                 /*
822                  * For YUV420P format the register contents are
823                  * duplicated in both VID registers
824                  */
825                 osd_modify(sd, OSD_MISCCTL_S420D, ~OSD_MISCCTL_S420D,
826                            OSD_MISCCTL);
827
828                 if (lconfig->interlaced) {
829                         osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN1YP);
830                         osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN1YL);
831                 } else {
832                         osd_write(sd, lconfig->ypos, OSD_VIDWIN1YP);
833                         osd_write(sd, lconfig->ysize, OSD_VIDWIN1YL);
834                 }
835                 break;
836         }
837 }
838
839 static int osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
840                                 struct osd_layer_config *lconfig)
841 {
842         struct osd_state *osd = sd;
843         struct osd_window_state *win = &osd->win[layer];
844         struct osd_layer_config *cfg = &win->lconfig;
845         unsigned long flags;
846         int reject_config;
847
848         spin_lock_irqsave(&osd->lock, flags);
849
850         reject_config = try_layer_config(sd, layer, lconfig);
851         if (reject_config) {
852                 spin_unlock_irqrestore(&osd->lock, flags);
853                 return reject_config;
854         }
855
856         /* update the current Cb/Cr order */
857         if (is_yc_pixfmt(lconfig->pixfmt))
858                 osd->yc_pixfmt = lconfig->pixfmt;
859
860         /*
861          * If we are switching OSD1 from normal mode to attribute mode or from
862          * attribute mode to normal mode, then we must disable the window.
863          */
864         if (layer == WIN_OSD1) {
865                 if (((lconfig->pixfmt == PIXFMT_OSD_ATTR) &&
866                   (cfg->pixfmt != PIXFMT_OSD_ATTR)) ||
867                   ((lconfig->pixfmt != PIXFMT_OSD_ATTR) &&
868                   (cfg->pixfmt == PIXFMT_OSD_ATTR))) {
869                         win->is_enabled = 0;
870                         _osd_disable_layer(sd, layer);
871                 }
872         }
873
874         _osd_set_layer_config(sd, layer, lconfig);
875
876         if (layer == WIN_OSD1) {
877                 struct osd_osdwin_state *osdwin_state =
878                     &osd->osdwin[OSDWIN_OSD1];
879
880                 if ((lconfig->pixfmt != PIXFMT_OSD_ATTR) &&
881                   (cfg->pixfmt == PIXFMT_OSD_ATTR)) {
882                         /*
883                          * We just switched OSD1 from attribute mode to normal
884                          * mode, so we must initialize the CLUT select, the
885                          * blend factor, transparency colorkey enable, and
886                          * attenuation enable (DM6446 only) bits in the
887                          * OSDWIN1MD register.
888                          */
889                         _osd_set_osd_clut(sd, OSDWIN_OSD1,
890                                                    osdwin_state->clut);
891                         _osd_set_blending_factor(sd, OSDWIN_OSD1,
892                                                           osdwin_state->blend);
893                         if (osdwin_state->colorkey_blending) {
894                                 _osd_enable_color_key(sd, OSDWIN_OSD1,
895                                                                osdwin_state->
896                                                                colorkey,
897                                                                lconfig->pixfmt);
898                         } else
899                                 _osd_disable_color_key(sd, OSDWIN_OSD1);
900                         _osd_set_rec601_attenuation(sd, OSDWIN_OSD1,
901                                                     osdwin_state->
902                                                     rec601_attenuation);
903                 } else if ((lconfig->pixfmt == PIXFMT_OSD_ATTR) &&
904                   (cfg->pixfmt != PIXFMT_OSD_ATTR)) {
905                         /*
906                          * We just switched OSD1 from normal mode to attribute
907                          * mode, so we must initialize the blink enable and
908                          * blink interval bits in the OSDATRMD register.
909                          */
910                         _osd_set_blink_attribute(sd, osd->is_blinking,
911                                                           osd->blink);
912                 }
913         }
914
915         /*
916          * If we just switched to a 1-, 2-, or 4-bits-per-pixel bitmap format
917          * then configure a default palette map.
918          */
919         if ((lconfig->pixfmt != cfg->pixfmt) &&
920           ((lconfig->pixfmt == PIXFMT_1BPP) ||
921           (lconfig->pixfmt == PIXFMT_2BPP) ||
922           (lconfig->pixfmt == PIXFMT_4BPP))) {
923                 enum osd_win_layer osdwin =
924                     ((layer == WIN_OSD0) ? OSDWIN_OSD0 : OSDWIN_OSD1);
925                 struct osd_osdwin_state *osdwin_state =
926                     &osd->osdwin[osdwin];
927                 unsigned char clut_index;
928                 unsigned char clut_entries = 0;
929
930                 switch (lconfig->pixfmt) {
931                 case PIXFMT_1BPP:
932                         clut_entries = 2;
933                         break;
934                 case PIXFMT_2BPP:
935                         clut_entries = 4;
936                         break;
937                 case PIXFMT_4BPP:
938                         clut_entries = 16;
939                         break;
940                 default:
941                         break;
942                 }
943                 /*
944                  * The default palette map maps the pixel value to the clut
945                  * index, i.e. pixel value 0 maps to clut entry 0, pixel value
946                  * 1 maps to clut entry 1, etc.
947                  */
948                 for (clut_index = 0; clut_index < 16; clut_index++) {
949                         osdwin_state->palette_map[clut_index] = clut_index;
950                         if (clut_index < clut_entries) {
951                                 _osd_set_palette_map(sd, osdwin, clut_index,
952                                                      clut_index,
953                                                      lconfig->pixfmt);
954                         }
955                 }
956         }
957
958         *cfg = *lconfig;
959         /* DM6446: configure the RGB888 enable and window selection */
960         if (osd->win[WIN_VID0].lconfig.pixfmt == PIXFMT_RGB888)
961                 _osd_enable_vid_rgb888(sd, WIN_VID0);
962         else if (osd->win[WIN_VID1].lconfig.pixfmt == PIXFMT_RGB888)
963                 _osd_enable_vid_rgb888(sd, WIN_VID1);
964         else
965                 _osd_disable_vid_rgb888(sd);
966
967         if (layer == WIN_VID0) {
968                 osd->pingpong =
969                     _osd_dm6446_vid0_pingpong(sd, osd->field_inversion,
970                                                        win->fb_base_phys,
971                                                        cfg);
972         }
973
974         spin_unlock_irqrestore(&osd->lock, flags);
975
976         return 0;
977 }
978
979 static void osd_init_layer(struct osd_state *sd, enum osd_layer layer)
980 {
981         struct osd_state *osd = sd;
982         struct osd_window_state *win = &osd->win[layer];
983         enum osd_win_layer osdwin;
984         struct osd_osdwin_state *osdwin_state;
985         struct osd_layer_config *cfg = &win->lconfig;
986         unsigned long flags;
987
988         spin_lock_irqsave(&osd->lock, flags);
989
990         win->is_enabled = 0;
991         _osd_disable_layer(sd, layer);
992
993         win->h_zoom = ZOOM_X1;
994         win->v_zoom = ZOOM_X1;
995         _osd_set_zoom(sd, layer, win->h_zoom, win->v_zoom);
996
997         win->fb_base_phys = 0;
998         _osd_start_layer(sd, layer, win->fb_base_phys, 0);
999
1000         cfg->line_length = 0;
1001         cfg->xsize = 0;
1002         cfg->ysize = 0;
1003         cfg->xpos = 0;
1004         cfg->ypos = 0;
1005         cfg->interlaced = 0;
1006         switch (layer) {
1007         case WIN_OSD0:
1008         case WIN_OSD1:
1009                 osdwin = (layer == WIN_OSD0) ? OSDWIN_OSD0 : OSDWIN_OSD1;
1010                 osdwin_state = &osd->osdwin[osdwin];
1011                 /*
1012                  * Other code relies on the fact that OSD windows default to a
1013                  * bitmap pixel format when they are deallocated, so don't
1014                  * change this default pixel format.
1015                  */
1016                 cfg->pixfmt = PIXFMT_8BPP;
1017                 _osd_set_layer_config(sd, layer, cfg);
1018                 osdwin_state->clut = RAM_CLUT;
1019                 _osd_set_osd_clut(sd, osdwin, osdwin_state->clut);
1020                 osdwin_state->colorkey_blending = 0;
1021                 _osd_disable_color_key(sd, osdwin);
1022                 osdwin_state->blend = OSD_8_VID_0;
1023                 _osd_set_blending_factor(sd, osdwin, osdwin_state->blend);
1024                 osdwin_state->rec601_attenuation = 0;
1025                 _osd_set_rec601_attenuation(sd, osdwin,
1026                                                      osdwin_state->
1027                                                      rec601_attenuation);
1028                 if (osdwin == OSDWIN_OSD1) {
1029                         osd->is_blinking = 0;
1030                         osd->blink = BLINK_X1;
1031                 }
1032                 break;
1033         case WIN_VID0:
1034         case WIN_VID1:
1035                 cfg->pixfmt = osd->yc_pixfmt;
1036                 _osd_set_layer_config(sd, layer, cfg);
1037                 break;
1038         }
1039
1040         spin_unlock_irqrestore(&osd->lock, flags);
1041 }
1042
1043 static void osd_release_layer(struct osd_state *sd, enum osd_layer layer)
1044 {
1045         struct osd_state *osd = sd;
1046         struct osd_window_state *win = &osd->win[layer];
1047         unsigned long flags;
1048
1049         spin_lock_irqsave(&osd->lock, flags);
1050
1051         if (!win->is_allocated) {
1052                 spin_unlock_irqrestore(&osd->lock, flags);
1053                 return;
1054         }
1055
1056         spin_unlock_irqrestore(&osd->lock, flags);
1057         osd_init_layer(sd, layer);
1058         spin_lock_irqsave(&osd->lock, flags);
1059
1060         win->is_allocated = 0;
1061
1062         spin_unlock_irqrestore(&osd->lock, flags);
1063 }
1064
1065 static int osd_request_layer(struct osd_state *sd, enum osd_layer layer)
1066 {
1067         struct osd_state *osd = sd;
1068         struct osd_window_state *win = &osd->win[layer];
1069         unsigned long flags;
1070
1071         spin_lock_irqsave(&osd->lock, flags);
1072
1073         if (win->is_allocated) {
1074                 spin_unlock_irqrestore(&osd->lock, flags);
1075                 return -1;
1076         }
1077         win->is_allocated = 1;
1078
1079         spin_unlock_irqrestore(&osd->lock, flags);
1080
1081         return 0;
1082 }
1083
1084 static void _osd_init(struct osd_state *sd)
1085 {
1086         osd_write(sd, 0, OSD_MODE);
1087         osd_write(sd, 0, OSD_VIDWINMD);
1088         osd_write(sd, 0, OSD_OSDWIN0MD);
1089         osd_write(sd, 0, OSD_OSDWIN1MD);
1090         osd_write(sd, 0, OSD_RECTCUR);
1091         osd_write(sd, 0, OSD_MISCCTL);
1092 }
1093
1094 static void osd_set_left_margin(struct osd_state *sd, u32 val)
1095 {
1096         osd_write(sd, val, OSD_BASEPX);
1097 }
1098
1099 static void osd_set_top_margin(struct osd_state *sd, u32 val)
1100 {
1101         osd_write(sd, val, OSD_BASEPY);
1102 }
1103
1104 static int osd_initialize(struct osd_state *osd)
1105 {
1106         if (osd == NULL)
1107                 return -ENODEV;
1108         _osd_init(osd);
1109
1110         /* set default Cb/Cr order */
1111         osd->yc_pixfmt = PIXFMT_YCbCrI;
1112
1113         _osd_set_field_inversion(osd, osd->field_inversion);
1114         _osd_set_rom_clut(osd, osd->rom_clut);
1115
1116         osd_init_layer(osd, WIN_OSD0);
1117         osd_init_layer(osd, WIN_VID0);
1118         osd_init_layer(osd, WIN_OSD1);
1119         osd_init_layer(osd, WIN_VID1);
1120
1121         return 0;
1122 }
1123
1124 static const struct vpbe_osd_ops osd_ops = {
1125         .initialize = osd_initialize,
1126         .request_layer = osd_request_layer,
1127         .release_layer = osd_release_layer,
1128         .enable_layer = osd_enable_layer,
1129         .disable_layer = osd_disable_layer,
1130         .set_layer_config = osd_set_layer_config,
1131         .get_layer_config = osd_get_layer_config,
1132         .start_layer = osd_start_layer,
1133         .set_left_margin = osd_set_left_margin,
1134         .set_top_margin = osd_set_top_margin,
1135 };
1136
1137 static int osd_probe(struct platform_device *pdev)
1138 {
1139         struct osd_platform_data *pdata;
1140         struct osd_state *osd;
1141         struct resource *res;
1142         int ret = 0;
1143
1144         osd = kzalloc(sizeof(struct osd_state), GFP_KERNEL);
1145         if (osd == NULL)
1146                 return -ENOMEM;
1147
1148         osd->dev = &pdev->dev;
1149         pdata = (struct osd_platform_data *)pdev->dev.platform_data;
1150         osd->vpbe_type = (enum vpbe_version)pdata->vpbe_type;
1151         if (NULL == pdev->dev.platform_data) {
1152                 dev_err(osd->dev, "No platform data defined for OSD"
1153                         " sub device\n");
1154                 ret = -ENOENT;
1155                 goto free_mem;
1156         }
1157
1158         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1159         if (!res) {
1160                 dev_err(osd->dev, "Unable to get OSD register address map\n");
1161                 ret = -ENODEV;
1162                 goto free_mem;
1163         }
1164         osd->osd_base_phys = res->start;
1165         osd->osd_size = res->end - res->start + 1;
1166         if (!request_mem_region(osd->osd_base_phys, osd->osd_size,
1167                                 MODULE_NAME)) {
1168                 dev_err(osd->dev, "Unable to reserve OSD MMIO region\n");
1169                 ret = -ENODEV;
1170                 goto free_mem;
1171         }
1172         osd->osd_base = (unsigned long)ioremap_nocache(res->start,
1173                                                         osd->osd_size);
1174         if (!osd->osd_base) {
1175                 dev_err(osd->dev, "Unable to map the OSD region\n");
1176                 ret = -ENODEV;
1177                 goto release_mem_region;
1178         }
1179         spin_lock_init(&osd->lock);
1180         osd->ops = osd_ops;
1181         platform_set_drvdata(pdev, osd);
1182         dev_notice(osd->dev, "OSD sub device probe success\n");
1183         return ret;
1184
1185 release_mem_region:
1186         release_mem_region(osd->osd_base_phys, osd->osd_size);
1187 free_mem:
1188         kfree(osd);
1189         return ret;
1190 }
1191
1192 static int osd_remove(struct platform_device *pdev)
1193 {
1194         struct osd_state *osd = platform_get_drvdata(pdev);
1195
1196         iounmap((void *)osd->osd_base);
1197         release_mem_region(osd->osd_base_phys, osd->osd_size);
1198         kfree(osd);
1199         return 0;
1200 }
1201
1202 static struct platform_driver osd_driver = {
1203         .probe          = osd_probe,
1204         .remove         = osd_remove,
1205         .driver         = {
1206                 .name   = MODULE_NAME,
1207                 .owner  = THIS_MODULE,
1208         },
1209 };
1210
1211 static int osd_init(void)
1212 {
1213         if (platform_driver_register(&osd_driver)) {
1214                 printk(KERN_ERR "Unable to register davinci osd driver\n");
1215                 return -ENODEV;
1216         }
1217
1218         return 0;
1219 }
1220
1221 static void osd_exit(void)
1222 {
1223         platform_driver_unregister(&osd_driver);
1224 }
1225
1226 module_init(osd_init);
1227 module_exit(osd_exit);
1228
1229 MODULE_LICENSE("GPL");
1230 MODULE_DESCRIPTION("DaVinci OSD Manager Driver");
1231 MODULE_AUTHOR("Texas Instruments");