root/drivers/media/platform/davinci/vpbe_osd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. osd_read
  2. osd_write
  3. osd_set
  4. osd_clear
  5. osd_modify
  6. _osd_dm6446_vid0_pingpong
  7. _osd_set_field_inversion
  8. _osd_set_blink_attribute
  9. _osd_set_rom_clut
  10. _osd_set_palette_map
  11. _osd_set_rec601_attenuation
  12. _osd_set_blending_factor
  13. _osd_enable_rgb888_pixblend
  14. _osd_enable_color_key
  15. _osd_disable_color_key
  16. _osd_set_osd_clut
  17. _osd_set_zoom
  18. _osd_disable_layer
  19. osd_disable_layer
  20. _osd_enable_attribute_mode
  21. _osd_enable_layer
  22. osd_enable_layer
  23. _osd_start_layer
  24. osd_start_layer
  25. osd_get_layer_config
  26. try_layer_config
  27. _osd_disable_vid_rgb888
  28. _osd_enable_vid_rgb888
  29. _osd_set_cbcr_order
  30. _osd_set_layer_config
  31. osd_set_layer_config
  32. osd_init_layer
  33. osd_release_layer
  34. osd_request_layer
  35. _osd_init
  36. osd_set_left_margin
  37. osd_set_top_margin
  38. osd_initialize
  39. osd_probe
  40. osd_remove

   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");

/* [<][>][^][v][top][bottom][index][help] */