Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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