#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <mach/cputype.h>
#include <mach/hardware.h>
#include <media/davinci/vpss.h>
#include <media/v4l2-device.h>
#include <media/davinci/vpbe_types.h>
#include <media/davinci/vpbe_osd.h>
#include <linux/io.h>
#include "vpbe_osd_regs.h"
#define MODULE_NAME "davinci-vpbe-osd"
static struct platform_device_id vpbe_osd_devtype[] = {
{
.name = DM644X_VPBE_OSD_SUBDEV_NAME,
.driver_data = VPBE_VERSION_1,
}, {
.name = DM365_VPBE_OSD_SUBDEV_NAME,
.driver_data = VPBE_VERSION_2,
}, {
.name = DM355_VPBE_OSD_SUBDEV_NAME,
.driver_data = VPBE_VERSION_3,
},
{
/* sentinel */
}
};
MODULE_DEVICE_TABLE(platform, vpbe_osd_devtype);
/* register access routines */
static inline u32 osd_read(struct osd_state *sd, u32 offset)
{
struct osd_state *osd = sd;
return readl(osd->osd_base + offset);
}
static inline u32 osd_write(struct osd_state *sd, u32 val, u32 offset)
{
struct osd_state *osd = sd;
writel(val, osd->osd_base + offset);
return val;
}
static inline u32 osd_set(struct osd_state *sd, u32 mask, u32 offset)
{
struct osd_state *osd = sd;
void __iomem *addr = osd->osd_base + offset;
u32 val = readl(addr) | mask;
writel(val, addr);
return val;
}
static inline u32 osd_clear(struct osd_state *sd, u32 mask, u32 offset)
{
struct osd_state *osd = sd;
void __iomem *addr = osd->osd_base + offset;
u32 val = readl(addr) & ~mask;
writel(val, addr);
return val;
}
static inline u32 osd_modify(struct osd_state *sd, u32 mask, u32 val,
u32 offset)
{
struct osd_state *osd = sd;
void __iomem *addr = osd->osd_base + offset;
u32 new_val = (readl(addr) & ~mask) | (val & mask);
writel(new_val, addr);
return new_val;
}
/* define some macros for layer and pixfmt classification */
#define is_osd_win(layer) (((layer) == WIN_OSD0) || ((layer) == WIN_OSD1))
#define is_vid_win(layer) (((layer) == WIN_VID0) || ((layer) == WIN_VID1))
#define is_rgb_pixfmt(pixfmt) \
(((pixfmt) == PIXFMT_RGB565) || ((pixfmt) == PIXFMT_RGB888))
#define is_yc_pixfmt(pixfmt) \
(((pixfmt) == PIXFMT_YCBCRI) || ((pixfmt) == PIXFMT_YCRCBI) || \
((pixfmt) == PIXFMT_NV12))
#define MAX_WIN_SIZE OSD_VIDWIN0XP_V0X
#define MAX_LINE_LENGTH (OSD_VIDWIN0OFST_V0LO << 5)
/**
* _osd_dm6446_vid0_pingpong() - field inversion fix for DM6446
* @sd - ptr to struct osd_state
* @field_inversion - inversion flag
* @fb_base_phys - frame buffer address
* @lconfig - ptr to layer config
*
* This routine implements a workaround for the field signal inversion silicon
* erratum described in Advisory 1.3.8 for the DM6446. The fb_base_phys and
* lconfig parameters apply to the vid0 window. This routine should be called
* whenever the vid0 layer configuration or start address is modified, or when
* the OSD field inversion setting is modified.
* Returns: 1 if the ping-pong buffers need to be toggled in the vsync isr, or
* 0 otherwise
*/
static int _osd_dm6446_vid0_pingpong(struct osd_state *sd,
int field_inversion,
unsigned long fb_base_phys,
const struct osd_layer_config *lconfig)
{
struct osd_platform_data *pdata;
pdata = (struct osd_platform_data *)sd->dev->platform_data;
if (pdata != NULL && pdata->field_inv_wa_enable) {
if (!field_inversion || !lconfig->interlaced) {
osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR);
osd_write(sd, fb_base_phys & ~0x1F, OSD_PPVWIN0ADR);
osd_modify(sd, OSD_MISCCTL_PPSW | OSD_MISCCTL_PPRV, 0,
OSD_MISCCTL);
return 0;
} else {
unsigned miscctl = OSD_MISCCTL_PPRV;
osd_write(sd,
(fb_base_phys & ~0x1F) - lconfig->line_length,
OSD_VIDWIN0ADR);
osd_write(sd,
(fb_base_phys & ~0x1F) + lconfig->line_length,
OSD_PPVWIN0ADR);
osd_modify(sd,
OSD_MISCCTL_PPSW | OSD_MISCCTL_PPRV, miscctl,
OSD_MISCCTL);
return 1;
}
}
return 0;
}
static void _osd_set_field_inversion(struct osd_state *sd, int enable)
{
unsigned fsinv = 0;
if (enable)
fsinv = OSD_MODE_FSINV;
osd_modify(sd, OSD_MODE_FSINV, fsinv, OSD_MODE);
}
static void _osd_set_blink_attribute(struct osd_state *sd, int enable,
enum osd_blink_interval blink)
{
u32 osdatrmd = 0;
if (enable) {
osdatrmd |= OSD_OSDATRMD_BLNK;
osdatrmd |= blink << OSD_OSDATRMD_BLNKINT_SHIFT;
}
/* caller must ensure that OSD1 is configured in attribute mode */
osd_modify(sd, OSD_OSDATRMD_BLNKINT | OSD_OSDATRMD_BLNK, osdatrmd,
OSD_OSDATRMD);
}
static void _osd_set_rom_clut(struct osd_state *sd,
enum osd_rom_clut rom_clut)
{
if (rom_clut == ROM_CLUT0)
osd_clear(sd, OSD_MISCCTL_RSEL, OSD_MISCCTL);
else
osd_set(sd, OSD_MISCCTL_RSEL, OSD_MISCCTL);
}
static void _osd_set_palette_map(struct osd_state *sd,
enum osd_win_layer osdwin,
unsigned char pixel_value,
unsigned char clut_index,
enum osd_pix_format pixfmt)
{
static const int map_2bpp[] = { 0, 5, 10, 15 };
static const int map_1bpp[] = { 0, 15 };
int bmp_offset;
int bmp_shift;
int bmp_mask;
int bmp_reg;
switch (pixfmt) {
case PIXFMT_1BPP:
bmp_reg = map_1bpp[pixel_value & 0x1];
break;
case PIXFMT_2BPP:
bmp_reg = map_2bpp[pixel_value & 0x3];
break;
case PIXFMT_4BPP:
bmp_reg = pixel_value & 0xf;
break;
default:
return;
}
switch (osdwin) {
case OSDWIN_OSD0:
bmp_offset = OSD_W0BMP01 + (bmp_reg >> 1) * sizeof(u32);
break;
case OSDWIN_OSD1:
bmp_offset = OSD_W1BMP01 + (bmp_reg >> 1) * sizeof(u32);
break;
default:
return;
}
if (bmp_reg & 1) {
bmp_shift = 8;
bmp_mask = 0xff << 8;
} else {
bmp_shift = 0;
bmp_mask = 0xff;
}
osd_modify(sd, bmp_mask, clut_index << bmp_shift, bmp_offset);
}
static void _osd_set_rec601_attenuation(struct osd_state *sd,
enum osd_win_layer osdwin, int enable)
{
switch (osdwin) {
case OSDWIN_OSD0:
osd_modify(sd, OSD_OSDWIN0MD_ATN0E,
enable ? OSD_OSDWIN0MD_ATN0E : 0,
OSD_OSDWIN0MD);
if (sd->vpbe_type == VPBE_VERSION_1)
osd_modify(sd, OSD_OSDWIN0MD_ATN0E,
enable ? OSD_OSDWIN0MD_ATN0E : 0,
OSD_OSDWIN0MD);
else if ((sd->vpbe_type == VPBE_VERSION_3) ||
(sd->vpbe_type == VPBE_VERSION_2))
osd_modify(sd, OSD_EXTMODE_ATNOSD0EN,
enable ? OSD_EXTMODE_ATNOSD0EN : 0,
OSD_EXTMODE);
break;
case OSDWIN_OSD1:
osd_modify(sd, OSD_OSDWIN1MD_ATN1E,
enable ? OSD_OSDWIN1MD_ATN1E : 0,
OSD_OSDWIN1MD);
if (sd->vpbe_type == VPBE_VERSION_1)
osd_modify(sd, OSD_OSDWIN1MD_ATN1E,
enable ? OSD_OSDWIN1MD_ATN1E : 0,
OSD_OSDWIN1MD);
else if ((sd->vpbe_type == VPBE_VERSION_3) ||
(sd->vpbe_type == VPBE_VERSION_2))
osd_modify(sd, OSD_EXTMODE_ATNOSD1EN,
enable ? OSD_EXTMODE_ATNOSD1EN : 0,
OSD_EXTMODE);
break;
}
}
static void _osd_set_blending_factor(struct osd_state *sd,
enum osd_win_layer osdwin,
enum osd_blending_factor blend)
{
switch (osdwin) {
case OSDWIN_OSD0:
osd_modify(sd, OSD_OSDWIN0MD_BLND0,
blend << OSD_OSDWIN0MD_BLND0_SHIFT, OSD_OSDWIN0MD);
break;
case OSDWIN_OSD1:
osd_modify(sd, OSD_OSDWIN1MD_BLND1,
blend << OSD_OSDWIN1MD_BLND1_SHIFT, OSD_OSDWIN1MD);
break;
}
}
static void _osd_enable_rgb888_pixblend(struct osd_state *sd,
enum osd_win_layer osdwin)
{
osd_modify(sd, OSD_MISCCTL_BLDSEL, 0, OSD_MISCCTL);
switch (osdwin) {
case OSDWIN_OSD0:
osd_modify(sd, OSD_EXTMODE_OSD0BLDCHR,
OSD_EXTMODE_OSD0BLDCHR, OSD_EXTMODE);
break;
case OSDWIN_OSD1:
osd_modify(sd, OSD_EXTMODE_OSD1BLDCHR,
OSD_EXTMODE_OSD1BLDCHR, OSD_EXTMODE);
break;
}
}
static void _osd_enable_color_key(struct osd_state *sd,
enum osd_win_layer osdwin,
unsigned colorkey,
enum osd_pix_format pixfmt)
{
switch (pixfmt) {
case PIXFMT_1BPP:
case PIXFMT_2BPP:
case PIXFMT_4BPP:
case PIXFMT_8BPP:
if (sd->vpbe_type == VPBE_VERSION_3) {
switch (osdwin) {
case OSDWIN_OSD0:
osd_modify(sd, OSD_TRANSPBMPIDX_BMP0,
colorkey <<
vpbe_osd.rar_linux osd
版权申诉
182 浏览量
2022-09-19
21:12:32
上传
评论
收藏 10KB RAR 举报
小贝德罗
- 粉丝: 70
- 资源: 1万+
最新资源
- 华为云会议安装包适配华为擎云L410 -1060 ARM架构
- 清空redis缓存脚本指令
- STM8S微控制器-寄存器操作指南
- apk一键安装,获取apk签名信息
- opencv4.8.0+contrib+cuda文件
- 【全网最新最全】大气公司年度月度总结汇报PPT
- C语言实现低功耗STM32F411开发板(原理图+PCB源文件+官方例程+驱动等).zip
- C语言实现基于STM32 的联合调试侦听设备解决方案(原理图、PCB源文件、调试工具、视频).zip
- 【全网最全最酷】部门年度年终工作总结汇报PPT模板
- C语言实现基于STM32F103RC的电子相册(原理图、PCB源文件、程序源码及制作).zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈