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