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#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
  29static 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
  45MODULE_DEVICE_TABLE(platform, vpbe_osd_devtype);
  46
  47/* register access routines */
  48static 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
  55static 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
  64static 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
  76static 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
  88static 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 */
 127static 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
 163static 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
 173static 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
 187static 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
 196static 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
 245static 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
 280static 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
 296static 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
 313static 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
 376static 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
 389static 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
 409static 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
 443static 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
 463static 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
 482static 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
 488static 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
 508static 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
 557static 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
 734static 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
 758static 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 */
 784static 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
 899static 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
 911static 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
 932static 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
 945static 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
1220static 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
1360static 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
1424static 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
1446static 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
1465static 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
1480static void osd_set_left_margin(struct osd_state *sd, u32 val)
1481{
1482        osd_write(sd, val, OSD_BASEPX);
1483}
1484
1485static void osd_set_top_margin(struct osd_state *sd, u32 val)
1486{
1487        osd_write(sd, val, OSD_BASEPY);
1488}
1489
1490static 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
1518static 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
1531static 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
1564static int osd_remove(struct platform_device *pdev)
1565{
1566        return 0;
1567}
1568
1569static 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
1578module_platform_driver(osd_driver);
1579
1580MODULE_LICENSE("GPL");
1581MODULE_DESCRIPTION("DaVinci OSD Manager Driver");
1582MODULE_AUTHOR("Texas Instruments");
1583