diff options
author | Tom Rini <trini@konsulko.com> | 2020-07-29 09:26:11 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2020-07-29 09:26:11 -0400 |
commit | 423e08cb77015beab6a81595765ec1faa34bedde (patch) | |
tree | 268fb246e025b8a5fc4eddc3c207ef428f16eb68 /drivers/video/nexell | |
parent | 3b191c56c841596771b4120f09fb556adf958b5c (diff) | |
parent | 3fad1ca28d4c87346d18b89438bf2084fb2c3896 (diff) |
Merge branch '2020-07-28-misc-soc-improvements'
- Assorted MediaTek improvements
- s5p4418 support
- QEMU ARM platform improvements
- Qualcomm IPQ40xx support
Diffstat (limited to 'drivers/video/nexell')
23 files changed, 8990 insertions, 0 deletions
diff --git a/drivers/video/nexell/Kconfig b/drivers/video/nexell/Kconfig new file mode 100644 index 0000000000..54b8ccb56e --- /dev/null +++ b/drivers/video/nexell/Kconfig @@ -0,0 +1,27 @@ +if VIDEO_NX + +menu "LCD select" + +config VIDEO_NX_RGB + bool "RGB LCD" + help + Support for RGB lcd output. + +config VIDEO_NX_LVDS + bool "LVDS LCD" + help + Support for LVDS lcd output. + +config VIDEO_NX_MIPI + bool "MiPi" + help + Support for MiPi lcd output. + +config VIDEO_NX_HDMI + bool "HDMI" + help + Support for hdmi output. + +endmenu + +endif diff --git a/drivers/video/nexell/Makefile b/drivers/video/nexell/Makefile new file mode 100644 index 0000000000..111ab4533c --- /dev/null +++ b/drivers/video/nexell/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2016 Nexell +# Junghyun, kim<jhkim@nexell.co.kr> + +obj-$(CONFIG_VIDEO_NX) += s5pxx18_dp.o +obj-$(CONFIG_VIDEO_NX) += soc/ + +obj-$(CONFIG_VIDEO_NX_RGB) += s5pxx18_dp_rgb.o +obj-$(CONFIG_VIDEO_NX_LVDS) += s5pxx18_dp_lvds.o +obj-$(CONFIG_VIDEO_NX_MIPI) += s5pxx18_dp_mipi.o +obj-$(CONFIG_VIDEO_NX_HDMI) += s5pxx18_dp_hdmi.o diff --git a/drivers/video/nexell/s5pxx18_dp.c b/drivers/video/nexell/s5pxx18_dp.c new file mode 100644 index 0000000000..2248f47905 --- /dev/null +++ b/drivers/video/nexell/s5pxx18_dp.c @@ -0,0 +1,341 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#include <config.h> +#include <common.h> +#include <errno.h> +#include <log.h> +#include <asm/arch/reset.h> +#include <asm/arch/nexell.h> +#include <asm/arch/display.h> + +#include "soc/s5pxx18_soc_disptop.h" +#include "soc/s5pxx18_soc_dpc.h" +#include "soc/s5pxx18_soc_mlc.h" + +#define MLC_LAYER_RGB_0 0 /* number of RGB layer 0 */ +#define MLC_LAYER_RGB_1 1 /* number of RGB layer 1 */ +#define MLC_LAYER_VIDEO 3 /* number of Video layer: 3 = VIDEO */ + +#define __io_address(a) (void *)(uintptr_t)(a) + +void dp_control_init(int module) +{ + void *base; + + /* top */ + base = __io_address(nx_disp_top_get_physical_address()); + nx_disp_top_set_base_address(base); + + /* control */ + base = __io_address(nx_dpc_get_physical_address(module)); + nx_dpc_set_base_address(module, base); + + /* top controller */ + nx_rstcon_setrst(RESET_ID_DISP_TOP, RSTCON_ASSERT); + nx_rstcon_setrst(RESET_ID_DISP_TOP, RSTCON_NEGATE); + + /* display controller */ + nx_rstcon_setrst(RESET_ID_DISPLAY, RSTCON_ASSERT); + nx_rstcon_setrst(RESET_ID_DISPLAY, RSTCON_NEGATE); + + nx_dpc_set_clock_pclk_mode(module, nx_pclkmode_always); +} + +int dp_control_setup(int module, + struct dp_sync_info *sync, struct dp_ctrl_info *ctrl) +{ + unsigned int out_format; + unsigned int delay_mask; + int rgb_pvd = 0, hsync_cp1 = 7, vsync_fram = 7, de_cp2 = 7; + int v_vso = 1, v_veo = 1, e_vso = 1, e_veo = 1; + + int interlace = 0; + int invert_field; + int swap_rb; + unsigned int yc_order; + int vck_select; + int vclk_invert; + int emb_sync; + + enum nx_dpc_dither r_dither, g_dither, b_dither; + int rgb_mode = 0; + + if (NULL == sync || NULL == ctrl) { + debug("error, dp.%d not set sync or pad clock info !!!\n", + module); + return -EINVAL; + } + + out_format = ctrl->out_format; + delay_mask = ctrl->delay_mask; + interlace = sync->interlace; + invert_field = ctrl->invert_field; + swap_rb = ctrl->swap_RB; + yc_order = ctrl->yc_order; + vck_select = ctrl->vck_select; + vclk_invert = ctrl->clk_inv_lv0 | ctrl->clk_inv_lv1; + emb_sync = (out_format == DPC_FORMAT_CCIR656 ? 1 : 0); + + /* set delay mask */ + if (delay_mask & DP_SYNC_DELAY_RGB_PVD) + rgb_pvd = ctrl->d_rgb_pvd; + if (delay_mask & DP_SYNC_DELAY_HSYNC_CP1) + hsync_cp1 = ctrl->d_hsync_cp1; + if (delay_mask & DP_SYNC_DELAY_VSYNC_FRAM) + vsync_fram = ctrl->d_vsync_fram; + if (delay_mask & DP_SYNC_DELAY_DE_CP) + de_cp2 = ctrl->d_de_cp2; + + if (ctrl->vs_start_offset != 0 || + ctrl->vs_end_offset != 0 || + ctrl->ev_start_offset != 0 || ctrl->ev_end_offset != 0) { + v_vso = ctrl->vs_start_offset; + v_veo = ctrl->vs_end_offset; + e_vso = ctrl->ev_start_offset; + e_veo = ctrl->ev_end_offset; + } + + if (nx_dpc_format_rgb555 == out_format || + nx_dpc_format_mrgb555a == out_format || + nx_dpc_format_mrgb555b == out_format) { + r_dither = nx_dpc_dither_5bit; + g_dither = nx_dpc_dither_5bit; + b_dither = nx_dpc_dither_5bit; + rgb_mode = 1; + } else if (nx_dpc_format_rgb565 == out_format || + nx_dpc_format_mrgb565 == out_format) { + r_dither = nx_dpc_dither_5bit; + b_dither = nx_dpc_dither_5bit; + g_dither = nx_dpc_dither_6bit, rgb_mode = 1; + } else if ((nx_dpc_format_rgb666 == out_format) || + (nx_dpc_format_mrgb666 == out_format)) { + r_dither = nx_dpc_dither_6bit; + g_dither = nx_dpc_dither_6bit; + b_dither = nx_dpc_dither_6bit; + rgb_mode = 1; + } else { + r_dither = nx_dpc_dither_bypass; + g_dither = nx_dpc_dither_bypass; + b_dither = nx_dpc_dither_bypass; + rgb_mode = 1; + } + + /* CLKGEN0/1 */ + nx_dpc_set_clock_source(module, 0, ctrl->clk_src_lv0 == 3 ? + 6 : ctrl->clk_src_lv0); + nx_dpc_set_clock_divisor(module, 0, ctrl->clk_div_lv0); + nx_dpc_set_clock_source(module, 1, ctrl->clk_src_lv1); + nx_dpc_set_clock_divisor(module, 1, ctrl->clk_div_lv1); + nx_dpc_set_clock_out_delay(module, 0, ctrl->clk_delay_lv0); + nx_dpc_set_clock_out_delay(module, 1, ctrl->clk_delay_lv1); + + /* LCD out */ + nx_dpc_set_mode(module, out_format, interlace, invert_field, + rgb_mode, swap_rb, yc_order, emb_sync, emb_sync, + vck_select, vclk_invert, 0); + nx_dpc_set_hsync(module, sync->h_active_len, sync->h_sync_width, + sync->h_front_porch, sync->h_back_porch, + sync->h_sync_invert); + nx_dpc_set_vsync(module, sync->v_active_len, sync->v_sync_width, + sync->v_front_porch, sync->v_back_porch, + sync->v_sync_invert, sync->v_active_len, + sync->v_sync_width, sync->v_front_porch, + sync->v_back_porch); + nx_dpc_set_vsync_offset(module, v_vso, v_veo, e_vso, e_veo); + nx_dpc_set_delay(module, rgb_pvd, hsync_cp1, vsync_fram, de_cp2); + nx_dpc_set_dither(module, r_dither, g_dither, b_dither); + + if (IS_ENABLED(CONFIG_MACH_S5P6818)) { + /* Set TFT_CLKCTRL (offset : 1030h) + * Field name : DPC0_CLKCTRL, DPC1_CLKCRL + * Default value : clk_inv_lv0/1 = 0 : PADCLK_InvCLK + * Invert case : clk_inv_lv0/1 = 1 : PADCLK_CLK + */ + if (module == 0 && ctrl->clk_inv_lv0) + nx_disp_top_set_padclock(padmux_primary_mlc, + padclk_clk); + if (module == 1 && ctrl->clk_inv_lv1) + nx_disp_top_set_padclock(padmux_secondary_mlc, + padclk_clk); + } + + debug("%s: dp.%d x:%4d, hf:%3d, hb:%3d, hs:%3d, hi=%d\n", + __func__, module, sync->h_active_len, sync->h_front_porch, + sync->h_back_porch, sync->h_sync_width, sync->h_sync_invert); + debug("%s: dp.%d y:%4d, vf:%3d, vb:%3d, vs:%3d, vi=%d\n", + __func__, module, sync->v_active_len, sync->v_front_porch, + sync->v_back_porch, sync->v_sync_width, sync->h_sync_invert); + debug("%s: dp.%d ck.0:%d:%d:%d, ck.1:%d:%d:%d\n", + __func__, module, + ctrl->clk_src_lv0, ctrl->clk_div_lv0, ctrl->clk_inv_lv0, + ctrl->clk_src_lv1, ctrl->clk_div_lv1, ctrl->clk_inv_lv1); + debug("%s: dp.%d vs:%d, ve:%d, es:%d, ee:%d\n", + __func__, module, v_vso, v_veo, e_vso, e_veo); + debug("%s: dp.%d delay RGB:%d, hs:%d, vs:%d, de:%d, fmt:0x%x\n", + __func__, module, rgb_pvd, hsync_cp1, vsync_fram, de_cp2, + out_format); + + return 0; +} + +void dp_control_enable(int module, int on) +{ + debug("%s: dp.%d top %s\n", __func__, module, on ? "ON" : "OFF"); + + nx_dpc_set_dpc_enable(module, on); + nx_dpc_set_clock_divisor_enable(module, on); +} + +void dp_plane_init(int module) +{ + void *base = __io_address(nx_mlc_get_physical_address(module)); + + nx_mlc_set_base_address(module, base); + nx_mlc_set_clock_pclk_mode(module, nx_pclkmode_always); + nx_mlc_set_clock_bclk_mode(module, nx_bclkmode_always); +} + +int dp_plane_screen_setup(int module, struct dp_plane_top *top) +{ + int width = top->screen_width; + int height = top->screen_height; + int interlace = top->interlace; + int video_prior = top->video_prior; + unsigned int bg_color = top->back_color; + + /* MLC TOP layer */ + nx_mlc_set_screen_size(module, width, height); + nx_mlc_set_layer_priority(module, video_prior); + nx_mlc_set_background(module, bg_color); + nx_mlc_set_field_enable(module, interlace); + nx_mlc_set_rgblayer_gama_table_power_mode(module, 0, 0, 0); + nx_mlc_set_rgblayer_gama_table_sleep_mode(module, 1, 1, 1); + nx_mlc_set_rgblayer_gamma_enable(module, 0); + nx_mlc_set_dither_enable_when_using_gamma(module, 0); + nx_mlc_set_gamma_priority(module, 0); + nx_mlc_set_top_power_mode(module, 1); + nx_mlc_set_top_sleep_mode(module, 0); + + debug("%s: dp.%d screen %dx%d, %s, priority:%d, bg:0x%x\n", + __func__, module, width, height, + interlace ? "Interlace" : "Progressive", + video_prior, bg_color); + + return 0; +} + +void dp_plane_screen_enable(int module, int on) +{ + /* enable top screen */ + nx_mlc_set_mlc_enable(module, on); + nx_mlc_set_top_dirty_flag(module); + debug("%s: dp.%d top %s\n", __func__, module, on ? "ON" : "OFF"); +} + +int dp_plane_layer_setup(int module, struct dp_plane_info *plane) +{ + int sx = plane->left; + int sy = plane->top; + int ex = sx + plane->width - 1; + int ey = sy + plane->height - 1; + int pixel_byte = plane->pixel_byte; + int mem_lock_size = 16; /* fix mem lock size */ + int layer = plane->layer; + unsigned int format = plane->format; + + if (!plane->enable) + return -EINVAL; + + /* MLC layer */ + nx_mlc_set_lock_size(module, layer, mem_lock_size); + nx_mlc_set_alpha_blending(module, layer, 0, 15); + nx_mlc_set_transparency(module, layer, 0, 0); + nx_mlc_set_color_inversion(module, layer, 0, 0); + nx_mlc_set_rgblayer_invalid_position(module, layer, 0, 0, 0, 0, 0, 0); + nx_mlc_set_rgblayer_invalid_position(module, layer, 1, 0, 0, 0, 0, 0); + nx_mlc_set_format_rgb(module, layer, format); + nx_mlc_set_position(module, layer, sx, sy, ex, ey); + nx_mlc_set_rgblayer_stride(module, layer, pixel_byte, + plane->width * pixel_byte); + nx_mlc_set_rgblayer_address(module, layer, plane->fb_base); + + debug("%s: dp.%d.%d %d * %d, %dbpp, fmt:0x%x\n", + __func__, module, layer, plane->width, plane->height, + pixel_byte * 8, format); + debug("%s: b:0x%x, l:%d, t:%d, r:%d, b:%d, hs:%d, vs:%d\n", + __func__, plane->fb_base, sx, sy, ex, ey, + plane->width * pixel_byte, pixel_byte); + + return 0; +} + +int dp_plane_set_enable(int module, int layer, int on) +{ + int hl, hc; + int vl, vc; + + debug("%s: dp.%d.%d %s:%s\n", + __func__, module, layer, + layer == MLC_LAYER_VIDEO ? "Video" : "RGB", + on ? "ON" : "OFF"); + + if (layer != MLC_LAYER_VIDEO) { + nx_mlc_set_layer_enable(module, layer, on); + nx_mlc_set_dirty_flag(module, layer); + return 0; + } + + /* video layer */ + if (on) { + nx_mlc_set_video_layer_line_buffer_power_mode(module, 1); + nx_mlc_set_video_layer_line_buffer_sleep_mode(module, 0); + nx_mlc_set_layer_enable(module, layer, 1); + nx_mlc_set_dirty_flag(module, layer); + } else { + nx_mlc_set_layer_enable(module, layer, 0); + nx_mlc_set_dirty_flag(module, layer); + nx_mlc_get_video_layer_scale_filter(module, + &hl, &hc, &vl, &vc); + if (hl || hc || vl || vc) + nx_mlc_set_video_layer_scale_filter(module, 0, 0, 0, 0); + nx_mlc_set_video_layer_line_buffer_power_mode(module, 0); + nx_mlc_set_video_layer_line_buffer_sleep_mode(module, 1); + nx_mlc_set_dirty_flag(module, layer); + } + + return 0; +} + +void dp_plane_layer_enable(int module, + struct dp_plane_info *plane, int on) +{ + dp_plane_set_enable(module, plane->layer, on); +} + +int dp_plane_set_address(int module, int layer, unsigned int address) +{ + nx_mlc_set_rgblayer_address(module, layer, address); + nx_mlc_set_dirty_flag(module, layer); + + return 0; +} + +int dp_plane_wait_vsync(int module, int layer, int fps) +{ + int cnt = 0; + + if (fps == 0) + return (int)nx_mlc_get_dirty_flag(module, layer); + + while (fps > cnt++) { + while (nx_mlc_get_dirty_flag(module, layer)) + ; + nx_mlc_set_dirty_flag(module, layer); + } + return 0; +} diff --git a/drivers/video/nexell/s5pxx18_dp_hdmi.c b/drivers/video/nexell/s5pxx18_dp_hdmi.c new file mode 100644 index 0000000000..3f1fb8a575 --- /dev/null +++ b/drivers/video/nexell/s5pxx18_dp_hdmi.c @@ -0,0 +1,545 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#include <config.h> +#include <common.h> +#include <errno.h> +#include <log.h> + +#include <asm/arch/nexell.h> +#include <asm/arch/tieoff.h> +#include <asm/arch/reset.h> +#include <asm/arch/display.h> + +#include <linux/delay.h> + +#include "soc/s5pxx18_soc_dpc.h" +#include "soc/s5pxx18_soc_hdmi.h" +#include "soc/s5pxx18_soc_disptop.h" +#include "soc/s5pxx18_soc_disptop_clk.h" + +#define __io_address(a) (void *)(uintptr_t)(a) + +static const u8 hdmiphy_preset74_25[32] = { + 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0xc8, 0x81, + 0xe8, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, 0x0a, + 0x80, 0x09, 0x84, 0x05, 0x22, 0x24, 0x86, 0x54, + 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x10, 0x80, +}; + +static const u8 hdmiphy_preset148_5[32] = { + 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0xc8, 0x81, + 0xe8, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, 0x0a, + 0x80, 0x09, 0x84, 0x05, 0x22, 0x24, 0x86, 0x54, + 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80, +}; + +#define HDMIPHY_PRESET_TABLE_SIZE (32) + +enum NXP_HDMI_PRESET { + NXP_HDMI_PRESET_720P = 0, /* 1280 x 720 */ + NXP_HDMI_PRESET_1080P, /* 1920 x 1080 */ + NXP_HDMI_PRESET_MAX +}; + +static void hdmi_reset(void) +{ + nx_rstcon_setrst(RESET_ID_HDMI_VIDEO, RSTCON_ASSERT); + nx_rstcon_setrst(RESET_ID_HDMI_SPDIF, RSTCON_ASSERT); + nx_rstcon_setrst(RESET_ID_HDMI_TMDS, RSTCON_ASSERT); + nx_rstcon_setrst(RESET_ID_HDMI_VIDEO, RSTCON_NEGATE); + nx_rstcon_setrst(RESET_ID_HDMI_SPDIF, RSTCON_NEGATE); + nx_rstcon_setrst(RESET_ID_HDMI_TMDS, RSTCON_NEGATE); +} + +static int hdmi_phy_enable(int preset, int enable) +{ + const u8 *table = NULL; + int size = 0; + u32 addr, i = 0; + + if (!enable) + return 0; + + switch (preset) { + case NXP_HDMI_PRESET_720P: + table = hdmiphy_preset74_25; + size = 32; + break; + case NXP_HDMI_PRESET_1080P: + table = hdmiphy_preset148_5; + size = 31; + break; + default: + printf("hdmi: phy not support preset %d\n", preset); + return -EINVAL; + } + + nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (0 << 7)); + nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (0 << 7)); + nx_hdmi_set_reg(0, HDMI_PHY_REG04, (0 << 4)); + nx_hdmi_set_reg(0, HDMI_PHY_REG04, (0 << 4)); + nx_hdmi_set_reg(0, HDMI_PHY_REG24, (1 << 7)); + nx_hdmi_set_reg(0, HDMI_PHY_REG24, (1 << 7)); + + for (i = 0, addr = HDMI_PHY_REG04; size > i; i++, addr += 4) { + nx_hdmi_set_reg(0, addr, table[i]); + nx_hdmi_set_reg(0, addr, table[i]); + } + + nx_hdmi_set_reg(0, HDMI_PHY_REG7C, 0x80); + nx_hdmi_set_reg(0, HDMI_PHY_REG7C, 0x80); + nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (1 << 7)); + nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (1 << 7)); + debug("%s: preset = %d\n", __func__, preset); + + return 0; +} + +static inline int hdmi_wait_phy_ready(void) +{ + int count = 500; + + do { + u32 val = nx_hdmi_get_reg(0, HDMI_LINK_PHY_STATUS_0); + + if (val & 0x01) { + printf("HDMI: phy ready...\n"); + return 1; + } + mdelay(10); + } while (count--); + + return 0; +} + +static inline int hdmi_get_vsync(int preset, + struct dp_sync_info *sync, + struct dp_ctrl_info *ctrl) +{ + switch (preset) { + case NXP_HDMI_PRESET_720P: /* 720p: 1280x720 */ + sync->h_active_len = 1280; + sync->h_sync_width = 40; + sync->h_back_porch = 220; + sync->h_front_porch = 110; + sync->h_sync_invert = 0; + sync->v_active_len = 720; + sync->v_sync_width = 5; + sync->v_back_porch = 20; + sync->v_front_porch = 5; + sync->v_sync_invert = 0; + break; + + case NXP_HDMI_PRESET_1080P: /* 1080p: 1920x1080 */ + sync->h_active_len = 1920; + sync->h_sync_width = 44; + sync->h_back_porch = 148; + sync->h_front_porch = 88; + sync->h_sync_invert = 0; + sync->v_active_len = 1080; + sync->v_sync_width = 5; + sync->v_back_porch = 36; + sync->v_front_porch = 4; + sync->v_sync_invert = 0; + break; + default: + printf("HDMI: not support preset sync %d\n", preset); + return -EINVAL; + } + + ctrl->clk_src_lv0 = 4; + ctrl->clk_div_lv0 = 1; + ctrl->clk_src_lv1 = 7; + ctrl->clk_div_lv1 = 1; + + ctrl->out_format = outputformat_rgb888; + ctrl->delay_mask = (DP_SYNC_DELAY_RGB_PVD | DP_SYNC_DELAY_HSYNC_CP1 | + DP_SYNC_DELAY_VSYNC_FRAM | DP_SYNC_DELAY_DE_CP); + ctrl->d_rgb_pvd = 0; + ctrl->d_hsync_cp1 = 0; + ctrl->d_vsync_fram = 0; + ctrl->d_de_cp2 = 7; + + /* HFP + HSW + HBP + AVWidth-VSCLRPIXEL- 1; */ + ctrl->vs_start_offset = (sync->h_front_porch + sync->h_sync_width + + sync->h_back_porch + sync->h_active_len - 1); + ctrl->vs_end_offset = 0; + + /* HFP + HSW + HBP + AVWidth-EVENVSCLRPIXEL- 1 */ + ctrl->ev_start_offset = (sync->h_front_porch + sync->h_sync_width + + sync->h_back_porch + sync->h_active_len - 1); + ctrl->ev_end_offset = 0; + debug("%s: preset: %d\n", __func__, preset); + + return 0; +} + +static void hdmi_clock(void) +{ + void *base = + __io_address(nx_disp_top_clkgen_get_physical_address + (to_mipi_clkgen)); + + nx_disp_top_clkgen_set_base_address(to_mipi_clkgen, base); + nx_disp_top_clkgen_set_clock_divisor_enable(to_mipi_clkgen, 0); + nx_disp_top_clkgen_set_clock_pclk_mode(to_mipi_clkgen, + nx_pclkmode_always); + nx_disp_top_clkgen_set_clock_source(to_mipi_clkgen, HDMI_SPDIF_CLKOUT, + 2); + nx_disp_top_clkgen_set_clock_divisor(to_mipi_clkgen, HDMI_SPDIF_CLKOUT, + 2); + nx_disp_top_clkgen_set_clock_source(to_mipi_clkgen, 1, 7); + nx_disp_top_clkgen_set_clock_divisor_enable(to_mipi_clkgen, 1); + + /* must initialize this !!! */ + nx_disp_top_hdmi_set_vsync_hsstart_end(0, 0); + nx_disp_top_hdmi_set_vsync_start(0); + nx_disp_top_hdmi_set_hactive_start(0); + nx_disp_top_hdmi_set_hactive_end(0); +} + +static void hdmi_vsync(struct dp_sync_info *sync) +{ + int width = sync->h_active_len; + int hsw = sync->h_sync_width; + int hbp = sync->h_back_porch; + int height = sync->v_active_len; + int vsw = sync->v_sync_width; + int vbp = sync->v_back_porch; + + int v_sync_s = vsw + vbp + height - 1; + int h_active_s = hsw + hbp; + int h_active_e = width + hsw + hbp; + int v_sync_hs_se0 = hsw + hbp + 1; + int v_sync_hs_se1 = hsw + hbp + 2; + + nx_disp_top_hdmi_set_vsync_start(v_sync_s); + nx_disp_top_hdmi_set_hactive_start(h_active_s); + nx_disp_top_hdmi_set_hactive_end(h_active_e); + nx_disp_top_hdmi_set_vsync_hsstart_end(v_sync_hs_se0, v_sync_hs_se1); +} + +static int hdmi_prepare(struct dp_sync_info *sync) +{ + int width = sync->h_active_len; + int hsw = sync->h_sync_width; + int hfp = sync->h_front_porch; + int hbp = sync->h_back_porch; + int height = sync->v_active_len; + int vsw = sync->v_sync_width; + int vfp = sync->v_front_porch; + int vbp = sync->v_back_porch; + + u32 h_blank, h_line, h_sync_start, h_sync_end; + u32 v_blank, v2_blank, v_line; + u32 v_sync_line_bef_1, v_sync_line_bef_2; + + u32 fixed_ffff = 0xffff; + + /* calculate sync variables */ + h_blank = hfp + hsw + hbp; + v_blank = vfp + vsw + vbp; + v2_blank = height + vfp + vsw + vbp; + v_line = height + vfp + vsw + vbp; /* total v */ + h_line = width + hfp + hsw + hbp; /* total h */ + h_sync_start = hfp; + h_sync_end = hfp + hsw; + v_sync_line_bef_1 = vfp; + v_sync_line_bef_2 = vfp + vsw; + + /* no blue screen mode, encoding order as it is */ + nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_0, (0 << 5) | (1 << 4)); + + /* set HDMI_LINK_BLUE_SCREEN_* to 0x0 */ + nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_R_0, 0x5555); + nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_R_1, 0x5555); + nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_G_0, 0x5555); + nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_G_1, 0x5555); + nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_B_0, 0x5555); + nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_B_1, 0x5555); + + /* set HDMI_CON_1 to 0x0 */ + nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_1, 0x0); + nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_2, 0x0); + + /* set interrupt : enable hpd_plug, hpd_unplug */ + nx_hdmi_set_reg(0, HDMI_LINK_INTC_CON_0, + (1 << 6) | (1 << 3) | (1 << 2)); + + /* set STATUS_EN to 0x17 */ + nx_hdmi_set_reg(0, HDMI_LINK_STATUS_EN, 0x17); + + /* TODO set HDP to 0x0 : later check hpd */ + nx_hdmi_set_reg(0, HDMI_LINK_HPD, 0x0); + + /* set MODE_SEL to 0x02 */ + nx_hdmi_set_reg(0, HDMI_LINK_MODE_SEL, 0x2); + + /* set H_BLANK_*, V1_BLANK_*, V2_BLANK_*, V_LINE_*, + * H_LINE_*, H_SYNC_START_*, H_SYNC_END_ * + * V_SYNC_LINE_BEF_1_*, V_SYNC_LINE_BEF_2_* + */ + nx_hdmi_set_reg(0, HDMI_LINK_H_BLANK_0, h_blank % 256); + nx_hdmi_set_reg(0, HDMI_LINK_H_BLANK_1, h_blank >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V1_BLANK_0, v_blank % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V1_BLANK_1, v_blank >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V2_BLANK_0, v2_blank % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V2_BLANK_1, v2_blank >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V_LINE_0, v_line % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_LINE_1, v_line >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_H_LINE_0, h_line % 256); + nx_hdmi_set_reg(0, HDMI_LINK_H_LINE_1, h_line >> 8); + + if (width == 1280) { + nx_hdmi_set_reg(0, HDMI_LINK_HSYNC_POL, 0x1); + nx_hdmi_set_reg(0, HDMI_LINK_VSYNC_POL, 0x1); + } else { + nx_hdmi_set_reg(0, HDMI_LINK_HSYNC_POL, 0x0); + nx_hdmi_set_reg(0, HDMI_LINK_VSYNC_POL, 0x0); + } + + nx_hdmi_set_reg(0, HDMI_LINK_INT_PRO_MODE, 0x0); + + nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_START_0, (h_sync_start % 256) - 2); + nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_START_1, h_sync_start >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_END_0, (h_sync_end % 256) - 2); + nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_END_1, h_sync_end >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_1_0, + v_sync_line_bef_1 % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_1_1, + v_sync_line_bef_1 >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_2_0, + v_sync_line_bef_2 % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_2_1, + v_sync_line_bef_2 >> 8); + + /* Set V_SYNC_LINE_AFT*, V_SYNC_LINE_AFT_PXL*, VACT_SPACE* */ + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_1_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_1_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_2_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_2_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_3_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_3_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_4_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_4_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_5_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_5_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_6_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_6_1, fixed_ffff >> 8); + + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_1_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_1_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_2_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_2_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_3_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_3_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_4_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_4_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_5_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_5_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_6_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_6_1, fixed_ffff >> 8); + + nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE1_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE1_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE2_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE2_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE3_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE3_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE4_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE4_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE5_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE5_1, fixed_ffff >> 8); + nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE6_0, fixed_ffff % 256); + nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE6_1, fixed_ffff >> 8); + + nx_hdmi_set_reg(0, HDMI_LINK_CSC_MUX, 0x0); + nx_hdmi_set_reg(0, HDMI_LINK_SYNC_GEN_MUX, 0x0); + + nx_hdmi_set_reg(0, HDMI_LINK_SEND_START_0, 0xfd); + nx_hdmi_set_reg(0, HDMI_LINK_SEND_START_1, 0x01); + nx_hdmi_set_reg(0, HDMI_LINK_SEND_END_0, 0x0d); + nx_hdmi_set_reg(0, HDMI_LINK_SEND_END_1, 0x3a); + nx_hdmi_set_reg(0, HDMI_LINK_SEND_END_2, 0x08); + + /* Set DC_CONTROL to 0x00 */ + nx_hdmi_set_reg(0, HDMI_LINK_DC_CONTROL, 0x0); + + if (IS_ENABLED(CONFIG_HDMI_PATTERN)) + nx_hdmi_set_reg(0, HDMI_LINK_VIDEO_PATTERN_GEN, 0x1); + else + nx_hdmi_set_reg(0, HDMI_LINK_VIDEO_PATTERN_GEN, 0x0); + + nx_hdmi_set_reg(0, HDMI_LINK_GCP_CON, 0x0a); + return 0; +} + +static void hdmi_init(void) +{ + void *base; + /** + * [SEQ 2] set the HDMI CLKGEN's PCLKMODE to always enabled + */ + base = + __io_address(nx_disp_top_clkgen_get_physical_address(hdmi_clkgen)); + nx_disp_top_clkgen_set_base_address(hdmi_clkgen, base); + nx_disp_top_clkgen_set_clock_pclk_mode(hdmi_clkgen, nx_pclkmode_always); + + base = __io_address(nx_hdmi_get_physical_address(0)); + nx_hdmi_set_base_address(0, base); + + /** + * [SEQ 3] set the 0xC001100C[0] to 1 + */ + nx_tieoff_set(NX_TIEOFF_DISPLAYTOP0_i_HDMI_PHY_REFCLK_SEL, 1); + + /** + * [SEQ 4] release the resets of HDMI.i_PHY_nRST and HDMI.i_nRST + */ + nx_rstcon_setrst(RESET_ID_HDMI_PHY, RSTCON_ASSERT); + nx_rstcon_setrst(RESET_ID_HDMI, RSTCON_ASSERT); + nx_rstcon_setrst(RESET_ID_HDMI_PHY, RSTCON_NEGATE); + nx_rstcon_setrst(RESET_ID_HDMI, RSTCON_NEGATE); +} + +void hdmi_enable(int input, int preset, struct dp_sync_info *sync, int enable) +{ + if (enable) { + nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_0, + (nx_hdmi_get_reg(0, HDMI_LINK_HDMI_CON_0) | + 0x1)); + hdmi_vsync(sync); + } else { + hdmi_phy_enable(preset, 0); + } +} + +static int hdmi_setup(int input, int preset, + struct dp_sync_info *sync, struct dp_ctrl_info *ctrl) +{ + u32 HDMI_SEL = 0; + int ret; + + switch (input) { + case DP_DEVICE_DP0: + HDMI_SEL = primary_mlc; + break; + case DP_DEVICE_DP1: + HDMI_SEL = secondary_mlc; + break; + case DP_DEVICE_RESCONV: + HDMI_SEL = resolution_conv; + break; + default: + printf("HDMI: not support source device %d\n", input); + return -EINVAL; + } + + /** + * [SEQ 5] set up the HDMI PHY to specific video clock. + */ + ret = hdmi_phy_enable(preset, 1); + if (ret < 0) + return ret; + + /** + * [SEQ 6] I2S (or SPDIFTX) configuration for the source audio data + * this is done in another user app - ex> Android Audio HAL + */ + + /** + * [SEQ 7] Wait for ECID ready + */ + + /** + * [SEQ 8] release the resets of HDMI.i_VIDEO_nRST and HDMI.i_SPDIF_nRST + * and HDMI.i_TMDS_nRST + */ + hdmi_reset(); + + /** + * [SEQ 9] Wait for HDMI PHY ready (wait until 0xC0200020.[0], 1) + */ + if (hdmi_wait_phy_ready() == 0) { + printf("%s: failed to wait for hdmiphy ready\n", __func__); + hdmi_phy_enable(preset, 0); + return -EIO; + } + /* set mux */ + nx_disp_top_set_hdmimux(1, HDMI_SEL); + + /** + * [SEC 10] Set the DPC CLKGEN's Source Clock to HDMI_CLK & + * Set Sync Parameter + */ + hdmi_clock(); + /* set hdmi link clk to clkgen vs default is hdmi phy clk */ + + /** + * [SEQ 11] Set up the HDMI Converter parameters + */ + hdmi_get_vsync(preset, sync, ctrl); + hdmi_prepare(sync); + + return 0; +} + +void nx_hdmi_display(int module, + struct dp_sync_info *sync, struct dp_ctrl_info *ctrl, + struct dp_plane_top *top, struct dp_plane_info *planes, + struct dp_hdmi_dev *dev) +{ + struct dp_plane_info *plane = planes; + int input = module == 0 ? DP_DEVICE_DP0 : DP_DEVICE_DP1; + int count = top->plane_num; + int preset = dev->preset; + int i = 0; + + debug("HDMI: display.%d\n", module); + + switch (preset) { + case 0: + top->screen_width = 1280; + top->screen_height = 720; + sync->h_active_len = 1280; + sync->v_active_len = 720; + break; + case 1: + top->screen_width = 1920; + top->screen_height = 1080; + sync->h_active_len = 1920; + sync->v_active_len = 1080; + break; + default: + printf("hdmi not support preset %d\n", preset); + return; + } + + printf("HDMI: display.%d, preset %d (%4d * %4d)\n", + module, preset, top->screen_width, top->screen_height); + + dp_control_init(module); + dp_plane_init(module); + + hdmi_init(); + hdmi_setup(input, preset, sync, ctrl); + + dp_plane_screen_setup(module, top); + for (i = 0; count > i; i++, plane++) { + if (!plane->enable) + continue; + dp_plane_layer_setup(module, plane); + dp_plane_layer_enable(module, plane, 1); + } + dp_plane_screen_enable(module, 1); + + dp_control_setup(module, sync, ctrl); + dp_control_enable(module, 1); + + hdmi_enable(input, preset, sync, 1); +} diff --git a/drivers/video/nexell/s5pxx18_dp_lvds.c b/drivers/video/nexell/s5pxx18_dp_lvds.c new file mode 100644 index 0000000000..f8ea63fdf1 --- /dev/null +++ b/drivers/video/nexell/s5pxx18_dp_lvds.c @@ -0,0 +1,274 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#include <config.h> +#include <common.h> +#include <errno.h> + +#include <asm/arch/nexell.h> +#include <asm/arch/reset.h> +#include <asm/arch/display.h> + +#include "soc/s5pxx18_soc_lvds.h" +#include "soc/s5pxx18_soc_disptop.h" +#include "soc/s5pxx18_soc_disptop_clk.h" + +#define __io_address(a) (void *)(uintptr_t)(a) + +static void lvds_phy_reset(void) +{ + nx_rstcon_setrst(RESET_ID_LVDS, RSTCON_ASSERT); + nx_rstcon_setrst(RESET_ID_LVDS, RSTCON_NEGATE); +} + +static void lvds_init(void) +{ + int clkid = DP_CLOCK_LVDS; + int index = 0; + void *base; + + base = __io_address(nx_disp_top_clkgen_get_physical_address(clkid)); + nx_disp_top_clkgen_set_base_address(clkid, base); + + nx_lvds_initialize(); + + for (index = 0; nx_lvds_get_number_of_module() > index; index++) + nx_lvds_set_base_address(index, + (void *)__io_address(nx_lvds_get_physical_address(index))); + + nx_disp_top_clkgen_set_clock_pclk_mode(clkid, nx_pclkmode_always); +} + +static void lvds_enable(int enable) +{ + int clkid = DP_CLOCK_LVDS; + int on = (enable ? 1 : 0); + + nx_disp_top_clkgen_set_clock_divisor_enable(clkid, on); +} + +static int lvds_setup(int module, int input, + struct dp_sync_info *sync, struct dp_ctrl_info *ctrl, + struct dp_lvds_dev *dev) +{ + unsigned int val; + int clkid = DP_CLOCK_LVDS; + enum dp_lvds_format format = DP_LVDS_FORMAT_JEIDA; + u32 voltage = DEF_VOLTAGE_LEVEL; + + if (dev) { + format = dev->lvds_format; + voltage = dev->voltage_level; + } + + printf("LVDS: "); + printf("%s, ", format == DP_LVDS_FORMAT_VESA ? "VESA" : + format == DP_LVDS_FORMAT_JEIDA ? "JEIDA" : "LOC"); + printf("voltage LV:0x%x\n", voltage); + + /* + *-------- predefined type. + * only change iTA to iTE in VESA mode + * wire [34:0] loc_VideoIn = + * {4'hf, 4'h0, i_VDEN, i_VSYNC, i_HSYNC, i_VD[23:0] }; + */ + u32 VSYNC = 25; + u32 HSYNC = 24; + u32 VDEN = 26; /* bit position */ + u32 ONE = 34; + u32 ZERO = 27; + + /*==================================================== + * current not use location mode + *==================================================== + */ + u32 LOC_A[7] = {ONE, ONE, ONE, ONE, ONE, ONE, ONE}; + u32 LOC_B[7] = {ONE, ONE, ONE, ONE, ONE, ONE, ONE}; + u32 LOC_C[7] = {VDEN, VSYNC, HSYNC, ONE, HSYNC, VSYNC, VDEN}; + u32 LOC_D[7] = {ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO}; + u32 LOC_E[7] = {ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO}; + + switch (input) { + case DP_DEVICE_DP0: + input = 0; + break; + case DP_DEVICE_DP1: + input = 1; + break; + case DP_DEVICE_RESCONV: + input = 2; + break; + default: + return -EINVAL; + } + + /* + * select TOP MUX + */ + nx_disp_top_clkgen_set_clock_divisor_enable(clkid, 0); + nx_disp_top_clkgen_set_clock_source(clkid, 0, ctrl->clk_src_lv0); + nx_disp_top_clkgen_set_clock_divisor(clkid, 0, ctrl->clk_div_lv0); + nx_disp_top_clkgen_set_clock_source(clkid, 1, ctrl->clk_src_lv1); + nx_disp_top_clkgen_set_clock_divisor(clkid, 1, ctrl->clk_div_lv1); + + /* + * LVDS Control Pin Setting + */ + val = (0 << 30) | /* CPU_I_VBLK_FLAG_SEL */ + (0 << 29) | /* CPU_I_BVLK_FLAG */ + (1 << 28) | /* SKINI_BST */ + (1 << 27) | /* DLYS_BST */ + (0 << 26) | /* I_AUTO_SEL */ + (format << 19) | /* JEiDA data packing */ + (0x1B << 13) | /* I_LOCK_PPM_SET, PPM setting for PLL lock */ + (0x638 << 1); /* I_DESKEW_CNT_SEL, period of de-skew region */ + nx_lvds_set_lvdsctrl0(0, val); + + val = (0 << 28) | /* I_ATE_MODE, function mode */ + (0 << 27) | /* I_TEST_CON_MODE, DA (test ctrl mode) */ + (0 << 24) | /* I_TX4010X_DUMMY */ + (0 << 15) | /* SKCCK 0 */ + (0 << 12) | /* SKC4 (TX output skew control pin at ODD ch4) */ + (0 << 9) | /* SKC3 (TX output skew control pin at ODD ch3) */ + (0 << 6) | /* SKC2 (TX output skew control pin at ODD ch2) */ + (0 << 3) | /* SKC1 (TX output skew control pin at ODD ch1) */ + (0 << 0); /* SKC0 (TX output skew control pin at ODD ch0) */ + nx_lvds_set_lvdsctrl1(0, val); + + val = (0 << 15) | /* CK_POL_SEL, Input clock, bypass */ + (0 << 14) | /* VSEL, VCO Freq. range. 0: Low(40MHz~90MHz), + * 1: High(90MHz~160MHz) */ + (0x1 << 12) | /* S (Post-scaler) */ + (0xA << 6) | /* M (Main divider) */ + (0xA << 0); /* P (Pre-divider) */ + + nx_lvds_set_lvdsctrl2(0, val); + val = (0x03 << 6) | /* SK_BIAS, Bias current ctrl pin */ + (0 << 5) | /* SKEWINI, skew selection pin, 0: bypass, + * 1: skew enable */ + (0 << 4) | /* SKEW_EN_H, skew block power down, 0: power down, + * 1: operating */ + (1 << 3) | /* CNTB_TDLY, delay control pin */ + (0 << 2) | /* SEL_DATABF, input clock 1/2 division cont. pin */ + (0x3 << 0); /* SKEW_REG_CUR, regulator bias current selection + * in SKEW block */ + + nx_lvds_set_lvdsctrl3(0, val); + val = (0 << 28) | /* FLT_CNT, filter control pin for PLL */ + (0 << 27) | /* VOD_ONLY_CNT, the pre-emphasis's pre-diriver + * control pin (VOD only) */ + (0 << 26) | /* CNNCT_MODE_SEL, connectivity mode selection, + * 0:TX operating, 1:con check */ + (0 << 24) | /* CNNCT_CNT, connectivity ctrl pin, + * 0: tx operating, 1: con check */ + (0 << 23) | /* VOD_HIGH_S, VOD control pin, 1: Vod only */ + (0 << 22) | /* SRC_TRH, source termination resistor sel. pin */ + (voltage << 14) | + (0x01 << 6) | /* CNT_PEN_H, TX driver pre-emphasis level cont. */ + (0x4 << 3) | /* FC_CODE, vos control pin */ + (0 << 2) | /* OUTCON, TX Driver state selectioin pin, 0:Hi-z, + * 1:Low */ + (0 << 1) | /* LOCK_CNT, Lock signal selection pin, enable */ + (0 << 0); /* AUTO_DSK_SEL, auto deskew sel. pin, normal */ + nx_lvds_set_lvdsctrl4(0, val); + + val = (0 << 24) | /* I_BIST_RESETB */ + (0 << 23) | /* I_BIST_EN */ + (0 << 21) | /* I_BIST_PAT_SEL */ + (0 << 14) | /* I_BIST_USER_PATTERN */ + (0 << 13) | /* I_BIST_FORCE_ERROR */ + (0 << 7) | /* I_BIST_SKEW_CTRL */ + (0 << 5) | /* I_BIST_CLK_INV */ + (0 << 3) | /* I_BIST_DATA_INV */ + (0 << 0); /* I_BIST_CH_SEL */ + nx_lvds_set_lvdstmode0(0, val); + + /* user do not need to modify this codes. */ + val = (LOC_A[4] << 24) | (LOC_A[3] << 18) | (LOC_A[2] << 12) | + (LOC_A[1] << 6) | (LOC_A[0] << 0); + nx_lvds_set_lvdsloc0(0, val); + + val = (LOC_B[2] << 24) | (LOC_B[1] << 18) | (LOC_B[0] << 12) | + (LOC_A[6] << 6) | (LOC_A[5] << 0); + nx_lvds_set_lvdsloc1(0, val); + + val = (LOC_C[0] << 24) | (LOC_B[6] << 18) | (LOC_B[5] << 12) | + (LOC_B[4] << 6) | (LOC_B[3] << 0); + nx_lvds_set_lvdsloc2(0, val); + + val = (LOC_C[5] << 24) | (LOC_C[4] << 18) | (LOC_C[3] << 12) | + (LOC_C[2] << 6) | (LOC_C[1] << 0); + nx_lvds_set_lvdsloc3(0, val); + + val = (LOC_D[3] << 24) | (LOC_D[2] << 18) | (LOC_D[1] << 12) | + (LOC_D[0] << 6) | (LOC_C[6] << 0); + nx_lvds_set_lvdsloc4(0, val); + + val = (LOC_E[1] << 24) | (LOC_E[0] << 18) | (LOC_D[6] << 12) | + (LOC_D[5] << 6) | (LOC_D[4] << 0); + nx_lvds_set_lvdsloc5(0, val); + + val = (LOC_E[6] << 24) | (LOC_E[5] << 18) | (LOC_E[4] << 12) | + (LOC_E[3] << 6) | (LOC_E[2] << 0); + nx_lvds_set_lvdsloc6(0, val); + + nx_lvds_set_lvdslocmask0(0, 0xffffffff); + nx_lvds_set_lvdslocmask1(0, 0xffffffff); + + nx_lvds_set_lvdslocpol0(0, (0 << 19) | (0 << 18)); + + /* + * select TOP MUX + */ + nx_disp_top_set_lvdsmux(1, input); + + /* + * LVDS PHY Reset, make sure last. + */ + lvds_phy_reset(); + + return 0; +} + +void nx_lvds_display(int module, + struct dp_sync_info *sync, struct dp_ctrl_info *ctrl, + struct dp_plane_top *top, struct dp_plane_info *planes, + struct dp_lvds_dev *dev) +{ + struct dp_plane_info *plane = planes; + int input = module == 0 ? DP_DEVICE_DP0 : DP_DEVICE_DP1; + int count = top->plane_num; + int i = 0; + + printf("LVDS: dp.%d\n", module); + + dp_control_init(module); + dp_plane_init(module); + + lvds_init(); + + /* set plane */ + dp_plane_screen_setup(module, top); + + for (i = 0; count > i; i++, plane++) { + if (!plane->enable) + continue; + dp_plane_layer_setup(module, plane); + dp_plane_layer_enable(module, plane, 1); + } + + dp_plane_screen_enable(module, 1); + + /* set lvds */ + lvds_setup(module, input, sync, ctrl, dev); + + lvds_enable(1); + + /* set dp control */ + dp_control_setup(module, sync, ctrl); + dp_control_enable(module, 1); +} diff --git a/drivers/video/nexell/s5pxx18_dp_mipi.c b/drivers/video/nexell/s5pxx18_dp_mipi.c new file mode 100644 index 0000000000..670272b268 --- /dev/null +++ b/drivers/video/nexell/s5pxx18_dp_mipi.c @@ -0,0 +1,677 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#include <config.h> +#include <common.h> +#include <errno.h> + +#include <asm/arch/nexell.h> +#include <asm/arch/tieoff.h> +#include <asm/arch/reset.h> +#include <asm/arch/display.h> + +#include "soc/s5pxx18_soc_mipi.h" +#include "soc/s5pxx18_soc_disptop.h" +#include "soc/s5pxx18_soc_disptop_clk.h" + +#define PLLPMS_1000MHZ 0x33E8 +#define BANDCTL_1000MHZ 0xF +#define PLLPMS_960MHZ 0x2280 +#define BANDCTL_960MHZ 0xF +#define PLLPMS_900MHZ 0x2258 +#define BANDCTL_900MHZ 0xE +#define PLLPMS_840MHZ 0x2230 +#define BANDCTL_840MHZ 0xD +#define PLLPMS_750MHZ 0x43E8 +#define BANDCTL_750MHZ 0xC +#define PLLPMS_660MHZ 0x21B8 +#define BANDCTL_660MHZ 0xB +#define PLLPMS_600MHZ 0x2190 +#define BANDCTL_600MHZ 0xA +#define PLLPMS_540MHZ 0x2168 +#define BANDCTL_540MHZ 0x9 +#define PLLPMS_512MHZ 0x03200 +#define BANDCTL_512MHZ 0x9 +#define PLLPMS_480MHZ 0x2281 +#define BANDCTL_480MHZ 0x8 +#define PLLPMS_420MHZ 0x2231 +#define BANDCTL_420MHZ 0x7 +#define PLLPMS_402MHZ 0x2219 +#define BANDCTL_402MHZ 0x7 +#define PLLPMS_330MHZ 0x21B9 +#define BANDCTL_330MHZ 0x6 +#define PLLPMS_300MHZ 0x2191 +#define BANDCTL_300MHZ 0x5 +#define PLLPMS_210MHZ 0x2232 +#define BANDCTL_210MHZ 0x4 +#define PLLPMS_180MHZ 0x21E2 +#define BANDCTL_180MHZ 0x3 +#define PLLPMS_150MHZ 0x2192 +#define BANDCTL_150MHZ 0x2 +#define PLLPMS_100MHZ 0x3323 +#define BANDCTL_100MHZ 0x1 +#define PLLPMS_80MHZ 0x3283 +#define BANDCTL_80MHZ 0x0 + +#define MIPI_INDEX 0 +#define MIPI_EXC_PRE_VALUE 1 +#define MIPI_DSI_IRQ_MASK 29 + +#define __io_address(a) (void *)(uintptr_t)(a) + +struct mipi_xfer_msg { + u8 id, data[2]; + u16 flags; + const u8 *tx_buf; + u16 tx_len; + u8 *rx_buf; + u16 rx_len; +}; + +static void mipi_reset(void) +{ + /* tieoff */ + nx_tieoff_set(NX_TIEOFF_MIPI0_NX_DPSRAM_1R1W_EMAA, 3); + nx_tieoff_set(NX_TIEOFF_MIPI0_NX_DPSRAM_1R1W_EMAB, 3); + + /* reset */ + nx_rstcon_setrst(RESET_ID_MIPI, RSTCON_ASSERT); + nx_rstcon_setrst(RESET_ID_MIPI_DSI, RSTCON_ASSERT); + nx_rstcon_setrst(RESET_ID_MIPI_CSI, RSTCON_ASSERT); + nx_rstcon_setrst(RESET_ID_MIPI_PHY_S, RSTCON_ASSERT); + nx_rstcon_setrst(RESET_ID_MIPI_PHY_M, RSTCON_ASSERT); + + nx_rstcon_setrst(RESET_ID_MIPI, RSTCON_NEGATE); + nx_rstcon_setrst(RESET_ID_MIPI_DSI, RSTCON_NEGATE); + nx_rstcon_setrst(RESET_ID_MIPI_PHY_S, RSTCON_NEGATE); + nx_rstcon_setrst(RESET_ID_MIPI_PHY_M, RSTCON_NEGATE); +} + +static void mipi_init(void) +{ + int clkid = DP_CLOCK_MIPI; + void *base; + + /* + * neet to reset before open + */ + mipi_reset(); + + base = __io_address(nx_disp_top_clkgen_get_physical_address(clkid)); + nx_disp_top_clkgen_set_base_address(clkid, base); + nx_disp_top_clkgen_set_clock_pclk_mode(clkid, nx_pclkmode_always); + + base = __io_address(nx_mipi_get_physical_address(0)); + nx_mipi_set_base_address(0, base); +} + +static int mipi_get_phy_pll(int bitrate, unsigned int *pllpms, + unsigned int *bandctl) +{ + unsigned int pms, ctl; + + switch (bitrate) { + case 1000: + pms = PLLPMS_1000MHZ; + ctl = BANDCTL_1000MHZ; + break; + case 960: + pms = PLLPMS_960MHZ; + ctl = BANDCTL_960MHZ; + break; + case 900: + pms = PLLPMS_900MHZ; + ctl = BANDCTL_900MHZ; + break; + case 840: + pms = PLLPMS_840MHZ; + ctl = BANDCTL_840MHZ; + break; + case 750: + pms = PLLPMS_750MHZ; + ctl = BANDCTL_750MHZ; + break; + case 660: + pms = PLLPMS_660MHZ; + ctl = BANDCTL_660MHZ; + break; + case 600: + pms = PLLPMS_600MHZ; + ctl = BANDCTL_600MHZ; + break; + case 540: + pms = PLLPMS_540MHZ; + ctl = BANDCTL_540MHZ; + break; + case 512: + pms = PLLPMS_512MHZ; + ctl = BANDCTL_512MHZ; + break; + case 480: + pms = PLLPMS_480MHZ; + ctl = BANDCTL_480MHZ; + break; + case 420: + pms = PLLPMS_420MHZ; + ctl = BANDCTL_420MHZ; + break; + case 402: + pms = PLLPMS_402MHZ; + ctl = BANDCTL_402MHZ; + break; + case 330: + pms = PLLPMS_330MHZ; + ctl = BANDCTL_330MHZ; + break; + case 300: + pms = PLLPMS_300MHZ; + ctl = BANDCTL_300MHZ; + break; + case 210: + pms = PLLPMS_210MHZ; + ctl = BANDCTL_210MHZ; + break; + case 180: + pms = PLLPMS_180MHZ; + ctl = BANDCTL_180MHZ; + break; + case 150: + pms = PLLPMS_150MHZ; + ctl = BANDCTL_150MHZ; + break; + case 100: + pms = PLLPMS_100MHZ; + ctl = BANDCTL_100MHZ; + break; + case 80: + pms = PLLPMS_80MHZ; + ctl = BANDCTL_80MHZ; + break; + default: + return -EINVAL; + } + + *pllpms = pms; + *bandctl = ctl; + + return 0; +} + +static int mipi_prepare(int module, int input, + struct dp_sync_info *sync, struct dp_ctrl_info *ctrl, + struct dp_mipi_dev *mipi) +{ + int index = MIPI_INDEX; + u32 esc_pre_value = MIPI_EXC_PRE_VALUE; + int lpm = mipi->lpm_trans; + int ret = 0; + + ret = mipi_get_phy_pll(mipi->hs_bitrate, + &mipi->hs_pllpms, &mipi->hs_bandctl); + if (ret < 0) + return ret; + + ret = mipi_get_phy_pll(mipi->lp_bitrate, + &mipi->lp_pllpms, &mipi->lp_bandctl); + if (ret < 0) + return ret; + + debug("%s: mipi lp:%dmhz:0x%x:0x%x, hs:%dmhz:0x%x:0x%x, %s trans\n", + __func__, mipi->lp_bitrate, mipi->lp_pllpms, mipi->lp_bandctl, + mipi->hs_bitrate, mipi->hs_pllpms, mipi->hs_bandctl, + lpm ? "low" : "high"); + + if (lpm) + nx_mipi_dsi_set_pll(index, 1, 0xFFFFFFFF, + mipi->lp_pllpms, mipi->lp_bandctl, 0, 0); + else + nx_mipi_dsi_set_pll(index, 1, 0xFFFFFFFF, + mipi->hs_pllpms, mipi->hs_bandctl, 0, 0); + +#ifdef CONFIG_ARCH_S5P4418 + /* + * disable the escape clock generating prescaler + * before soft reset. + */ + nx_mipi_dsi_set_clock(index, 0, 0, 1, 1, 1, 0, 0, 0, 0, 10); + mdelay(1); +#endif + + nx_mipi_dsi_software_reset(index); + nx_mipi_dsi_set_clock(index, 0, 0, 1, 1, 1, 0, 0, 0, 1, esc_pre_value); + nx_mipi_dsi_set_phy(index, 0, 1, 1, 0, 0, 0, 0, 0); + + if (lpm) + nx_mipi_dsi_set_escape_lp(index, nx_mipi_dsi_lpmode_lp, + nx_mipi_dsi_lpmode_lp); + else + nx_mipi_dsi_set_escape_lp(index, nx_mipi_dsi_lpmode_hs, + nx_mipi_dsi_lpmode_hs); + mdelay(20); + + return 0; +} + +static int mipi_enable(int module, int input, + struct dp_sync_info *sync, struct dp_ctrl_info *ctrl, + struct dp_mipi_dev *mipi) +{ + struct mipi_dsi_device *dsi = &mipi->dsi; + int clkid = DP_CLOCK_MIPI; + int index = MIPI_INDEX; + int width = sync->h_active_len; + int height = sync->v_active_len; + int HFP = sync->h_front_porch; + int HBP = sync->h_back_porch; + int HS = sync->h_sync_width; + int VFP = sync->v_front_porch; + int VBP = sync->v_back_porch; + int VS = sync->v_sync_width; + int en_prescaler = 1; + u32 esc_pre_value = MIPI_EXC_PRE_VALUE; + + int txhsclock = 1; + int lpm = mipi->lpm_trans; + bool command_mode = mipi->command_mode; + + enum nx_mipi_dsi_format dsi_format; + int data_len = dsi->lanes - 1; + bool burst = dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST ? true : false; + bool eot_enable = dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET ? + false : true; + + /* + * disable the escape clock generating prescaler + * before soft reset. + */ +#ifdef CONFIG_ARCH_S5P4418 + en_prescaler = 0; +#endif + + debug("%s: mode:%s, lanes.%d\n", __func__, + command_mode ? "command" : "video", data_len + 1); + + if (lpm) + nx_mipi_dsi_set_escape_lp(index, + nx_mipi_dsi_lpmode_hs, + nx_mipi_dsi_lpmode_hs); + + nx_mipi_dsi_set_pll(index, 1, 0xFFFFFFFF, + mipi->hs_pllpms, mipi->hs_bandctl, 0, 0); + mdelay(1); + + nx_mipi_dsi_set_clock(index, 0, 0, 1, 1, 1, 0, 0, 0, en_prescaler, 10); + mdelay(1); + + nx_mipi_dsi_software_reset(index); + nx_mipi_dsi_set_clock(index, txhsclock, 0, 1, + 1, 1, 0, 0, 0, 1, esc_pre_value); + + switch (data_len) { + case 0: /* 1 lane */ + nx_mipi_dsi_set_phy(index, data_len, 1, 1, 0, 0, 0, 0, 0); + break; + case 1: /* 2 lane */ + nx_mipi_dsi_set_phy(index, data_len, 1, 1, 1, 0, 0, 0, 0); + break; + case 2: /* 3 lane */ + nx_mipi_dsi_set_phy(index, data_len, 1, 1, 1, 1, 0, 0, 0); + break; + case 3: /* 3 lane */ + nx_mipi_dsi_set_phy(index, data_len, 1, 1, 1, 1, 1, 0, 0); + break; + default: + printf("%s: not support data lanes %d\n", + __func__, data_len + 1); + return -EINVAL; + } + + switch (dsi->format) { + case MIPI_DSI_FMT_RGB565: + dsi_format = nx_mipi_dsi_format_rgb565; + break; + case MIPI_DSI_FMT_RGB666: + dsi_format = nx_mipi_dsi_format_rgb666; + break; + case MIPI_DSI_FMT_RGB666_PACKED: + dsi_format = nx_mipi_dsi_format_rgb666_packed; + break; + case MIPI_DSI_FMT_RGB888: + dsi_format = nx_mipi_dsi_format_rgb888; + break; + default: + printf("%s: not support format %d\n", __func__, dsi->format); + return -EINVAL; + } + + nx_mipi_dsi_set_config_video_mode(index, 1, 0, burst, + nx_mipi_dsi_syncmode_event, + eot_enable, 1, 1, 1, 1, 0, dsi_format, + HFP, HBP, HS, VFP, VBP, VS, 0); + + nx_mipi_dsi_set_size(index, width, height); + + /* set mux */ + nx_disp_top_set_mipimux(1, module); + + /* 0 is spdif, 1 is mipi vclk */ + nx_disp_top_clkgen_set_clock_source(clkid, 1, ctrl->clk_src_lv0); + nx_disp_top_clkgen_set_clock_divisor(clkid, 1, + ctrl->clk_div_lv1 * + ctrl->clk_div_lv0); + + /* SPDIF and MIPI */ + nx_disp_top_clkgen_set_clock_divisor_enable(clkid, 1); + + /* START: CLKGEN, MIPI is started in setup function */ + nx_disp_top_clkgen_set_clock_divisor_enable(clkid, true); + nx_mipi_dsi_set_enable(index, true); + + return 0; +} + +static int nx_mipi_transfer_tx(struct mipi_dsi_device *dsi, + struct mipi_xfer_msg *xfer) +{ + const u8 *txb; + int size, index = 0; + u32 data; + + if (xfer->tx_len > DSI_TX_FIFO_SIZE) + printf("warn: tx %d size over fifo %d\n", + (int)xfer->tx_len, DSI_TX_FIFO_SIZE); + + /* write payload */ + size = xfer->tx_len; + txb = xfer->tx_buf; + + while (size >= 4) { + data = (txb[3] << 24) | (txb[2] << 16) | + (txb[1] << 8) | (txb[0]); + nx_mipi_dsi_write_payload(index, data); + txb += 4, size -= 4; + data = 0; + } + + switch (size) { + case 3: + data |= txb[2] << 16; + case 2: + data |= txb[1] << 8; + case 1: + data |= txb[0]; + nx_mipi_dsi_write_payload(index, data); + break; + case 0: + break; /* no payload */ + } + + /* write packet hdr */ + data = (xfer->data[1] << 16) | (xfer->data[0] << 8) | xfer->id; + + nx_mipi_dsi_write_pkheader(index, data); + + return 0; +} + +static int nx_mipi_transfer_done(struct mipi_dsi_device *dsi) +{ + int index = 0, count = 100; + u32 value; + + do { + mdelay(1); + value = nx_mipi_dsi_read_fifo_status(index); + if (((1 << 22) & value)) + break; + } while (count-- > 0); + + if (count < 0) + return -EINVAL; + + return 0; +} + +static int nx_mipi_transfer_rx(struct mipi_dsi_device *dsi, + struct mipi_xfer_msg *xfer) +{ + u8 *rxb = xfer->rx_buf; + int index = 0, rx_len = 0; + u32 data, count = 0; + u16 size; + int err = -EINVAL; + + nx_mipi_dsi_clear_interrupt_pending(index, 18); + + while (1) { + /* Completes receiving data. */ + if (nx_mipi_dsi_get_interrupt_pending(index, 18)) + break; + + mdelay(1); + + if (count > 500) { + printf("%s: error recevice data\n", __func__); + err = -EINVAL; + goto clear_fifo; + } else { + count++; + } + } + + data = nx_mipi_dsi_read_fifo(index); + + switch (data & 0x3f) { + case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE: + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE: + if (xfer->rx_len >= 2) { + rxb[1] = data >> 16; + rx_len++; + } + + /* Fall through */ + case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE: + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE: + rxb[0] = data >> 8; + rx_len++; + xfer->rx_len = rx_len; + err = rx_len; + goto clear_fifo; + + case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT: + printf("DSI Error Report: 0x%04x\n", (data >> 8) & 0xffff); + err = rx_len; + goto clear_fifo; + } + + size = (data >> 8) & 0xffff; + + if (size > xfer->rx_len) + size = xfer->rx_len; + else if (size < xfer->rx_len) + xfer->rx_len = size; + + size = xfer->rx_len - rx_len; + rx_len += size; + + /* Receive payload */ + while (size >= 4) { + data = nx_mipi_dsi_read_fifo(index); + rxb[0] = (data >> 0) & 0xff; + rxb[1] = (data >> 8) & 0xff; + rxb[2] = (data >> 16) & 0xff; + rxb[3] = (data >> 24) & 0xff; + rxb += 4, size -= 4; + } + + if (size) { + data = nx_mipi_dsi_read_fifo(index); + switch (size) { + case 3: + rxb[2] = (data >> 16) & 0xff; + case 2: + rxb[1] = (data >> 8) & 0xff; + case 1: + rxb[0] = data & 0xff; + } + } + + if (rx_len == xfer->rx_len) + err = rx_len; + +clear_fifo: + size = DSI_RX_FIFO_SIZE / 4; + do { + data = nx_mipi_dsi_read_fifo(index); + if (data == DSI_RX_FIFO_EMPTY) + break; + } while (--size); + + return err; +} + +#define IS_SHORT(t) (9 > ((t) & 0x0f)) + +static int nx_mipi_transfer(struct mipi_dsi_device *dsi, + const struct mipi_dsi_msg *msg) +{ + struct mipi_xfer_msg xfer; + int err; + + if (!msg->tx_len) + return -EINVAL; + + /* set id */ + xfer.id = msg->type | (msg->channel << 6); + + /* short type msg */ + if (IS_SHORT(msg->type)) { + const char *txb = msg->tx_buf; + + if (msg->tx_len > 2) + return -EINVAL; + + xfer.tx_len = 0; /* no payload */ + xfer.data[0] = txb[0]; + xfer.data[1] = (msg->tx_len == 2) ? txb[1] : 0; + xfer.tx_buf = NULL; + } else { + xfer.tx_len = msg->tx_len; + xfer.data[0] = msg->tx_len & 0xff; + xfer.data[1] = msg->tx_len >> 8; + xfer.tx_buf = msg->tx_buf; + } + + xfer.rx_len = msg->rx_len; + xfer.rx_buf = msg->rx_buf; + xfer.flags = msg->flags; + + err = nx_mipi_transfer_tx(dsi, &xfer); + + if (xfer.rx_len) + err = nx_mipi_transfer_rx(dsi, &xfer); + + nx_mipi_transfer_done(dsi); + + return err; +} + +static ssize_t nx_mipi_write_buffer(struct mipi_dsi_device *dsi, + const void *data, size_t len) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .tx_buf = data, + .tx_len = len + }; + + switch (len) { + case 0: + return -EINVAL; + case 1: + msg.type = MIPI_DSI_DCS_SHORT_WRITE; + break; + case 2: + msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM; + break; + default: + msg.type = MIPI_DSI_DCS_LONG_WRITE; + break; + } + + if (dsi->mode_flags & MIPI_DSI_MODE_LPM) + msg.flags |= MIPI_DSI_MSG_USE_LPM; + + return nx_mipi_transfer(dsi, &msg); +} + +__weak int nx_mipi_dsi_lcd_bind(struct mipi_dsi_device *dsi) +{ + return 0; +} + +/* + * disply + * MIPI DSI Setting + * (1) Initiallize MIPI(DSIM,DPHY,PLL) + * (2) Initiallize LCD + * (3) ReInitiallize MIPI(DSIM only) + * (4) Turn on display(MLC,DPC,...) + */ +void nx_mipi_display(int module, + struct dp_sync_info *sync, struct dp_ctrl_info *ctrl, + struct dp_plane_top *top, struct dp_plane_info *planes, + struct dp_mipi_dev *dev) +{ + struct dp_plane_info *plane = planes; + struct mipi_dsi_device *dsi = &dev->dsi; + int input = module == 0 ? DP_DEVICE_DP0 : DP_DEVICE_DP1; + int count = top->plane_num; + int i = 0, ret; + + printf("MIPI: dp.%d\n", module); + + /* map mipi-dsi write callback func */ + dsi->write_buffer = nx_mipi_write_buffer; + + ret = nx_mipi_dsi_lcd_bind(dsi); + if (ret) { + printf("Error: bind mipi-dsi lcd driver !\n"); + return; + } + + dp_control_init(module); + dp_plane_init(module); + + mipi_init(); + + /* set plane */ + dp_plane_screen_setup(module, top); + + for (i = 0; count > i; i++, plane++) { + if (!plane->enable) + continue; + dp_plane_layer_setup(module, plane); + dp_plane_layer_enable(module, plane, 1); + } + dp_plane_screen_enable(module, 1); + + /* set mipi */ + mipi_prepare(module, input, sync, ctrl, dev); + + if (dsi->ops && dsi->ops->prepare) + dsi->ops->prepare(dsi); + + if (dsi->ops && dsi->ops->enable) + dsi->ops->enable(dsi); + + mipi_enable(module, input, sync, ctrl, dev); + + /* set dp control */ + dp_control_setup(module, sync, ctrl); + dp_control_enable(module, 1); +} diff --git a/drivers/video/nexell/s5pxx18_dp_rgb.c b/drivers/video/nexell/s5pxx18_dp_rgb.c new file mode 100644 index 0000000000..44e8edb02a --- /dev/null +++ b/drivers/video/nexell/s5pxx18_dp_rgb.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#include <config.h> +#include <common.h> +#include <errno.h> + +#include <asm/arch/display.h> + +#include "soc/s5pxx18_soc_disptop.h" + +static int rgb_switch(int module, int input, struct dp_sync_info *sync, + struct dp_rgb_dev *dev) +{ + int mpu = dev->lcd_mpu_type; + int rsc = 0, sel = 0; + + switch (module) { + case 0: + sel = mpu ? 1 : 0; + break; + case 1: + sel = rsc ? 3 : 2; + break; + default: + printf("Fail, %s nuknown module %d\n", __func__, module); + return -1; + } + + nx_disp_top_set_primary_mux(sel); + return 0; +} + +void nx_rgb_display(int module, + struct dp_sync_info *sync, struct dp_ctrl_info *ctrl, + struct dp_plane_top *top, struct dp_plane_info *planes, + struct dp_rgb_dev *dev) +{ + struct dp_plane_info *plane = planes; + int input = module == 0 ? DP_DEVICE_DP0 : DP_DEVICE_DP1; + int count = top->plane_num; + int i = 0; + + printf("RGB: dp.%d\n", module); + + dp_control_init(module); + dp_plane_init(module); + + /* set plane */ + dp_plane_screen_setup(module, top); + + for (i = 0; count > i; i++, plane++) { + if (!plane->enable) + continue; + dp_plane_layer_setup(module, plane); + dp_plane_layer_enable(module, plane, 1); + } + + dp_plane_screen_enable(module, 1); + + rgb_switch(module, input, sync, dev); + + dp_control_setup(module, sync, ctrl); + dp_control_enable(module, 1); +} diff --git a/drivers/video/nexell/soc/Makefile b/drivers/video/nexell/soc/Makefile new file mode 100644 index 0000000000..a3036e52ee --- /dev/null +++ b/drivers/video/nexell/soc/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2016 Nexell +# Junghyun, kim<jhkim@nexell.co.kr> + +obj-$(CONFIG_VIDEO_NX) += s5pxx18_soc_dpc.o s5pxx18_soc_mlc.o \ + s5pxx18_soc_disptop.o s5pxx18_soc_disptop_clk.o + +obj-$(CONFIG_VIDEO_NX_LVDS) += s5pxx18_soc_lvds.o +obj-$(CONFIG_VIDEO_NX_MIPI) += s5pxx18_soc_mipi.o +obj-$(CONFIG_VIDEO_NX_HDMI) += s5pxx18_soc_hdmi.o diff --git a/drivers/video/nexell/soc/s5pxx18_soc_disptop.c b/drivers/video/nexell/soc/s5pxx18_soc_disptop.c new file mode 100644 index 0000000000..626e53a876 --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_disptop.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#include <linux/types.h> +#include <linux/io.h> + +#include "s5pxx18_soc_disptop.h" + +static struct { + struct nx_disp_top_register_set *pregister; +} __g_module_variables = { NULL, }; + +int nx_disp_top_initialize(void) +{ + static int binit; + u32 i; + + if (binit == 0) { + for (i = 0; i < NUMBER_OF_DISPTOP_MODULE; i++) + __g_module_variables.pregister = NULL; + binit = 1; + } + return 1; +} + +u32 nx_disp_top_get_number_of_module(void) +{ + return NUMBER_OF_DISPTOP_MODULE; +} + +u32 nx_disp_top_get_physical_address(void) +{ + static const u32 physical_addr[] = PHY_BASEADDR_DISPTOP_LIST; + + return (u32)(physical_addr[0] + PHY_BASEADDR_DISPLAYTOP_MODULE_OFFSET); +} + +u32 nx_disp_top_get_size_of_register_set(void) +{ + return sizeof(struct nx_disp_top_register_set); +} + +void nx_disp_top_set_base_address(void *base_address) +{ + __g_module_variables.pregister = + (struct nx_disp_top_register_set *)base_address; +} + +void *nx_disp_top_get_base_address(void) +{ + return (void *)__g_module_variables.pregister; +} + +void nx_disp_top_set_resconvmux(int benb, u32 sel) +{ + register struct nx_disp_top_register_set *pregister; + u32 regvalue; + + pregister = __g_module_variables.pregister; + regvalue = (benb << 31) | (sel << 0); + writel((u32)regvalue, &pregister->resconv_mux_ctrl); +} + +void nx_disp_top_set_hdmimux(int benb, u32 sel) +{ + register struct nx_disp_top_register_set *pregister; + u32 regvalue; + + pregister = __g_module_variables.pregister; + regvalue = (benb << 31) | (sel << 0); + writel((u32)regvalue, &pregister->interconv_mux_ctrl); +} + +void nx_disp_top_set_mipimux(int benb, u32 sel) +{ + register struct nx_disp_top_register_set *pregister; + u32 regvalue; + + pregister = __g_module_variables.pregister; + regvalue = (benb << 31) | (sel << 0); + writel((u32)regvalue, &pregister->mipi_mux_ctrl); +} + +void nx_disp_top_set_lvdsmux(int benb, u32 sel) +{ + register struct nx_disp_top_register_set *pregister; + u32 regvalue; + + pregister = __g_module_variables.pregister; + regvalue = (benb << 31) | (sel << 0); + writel((u32)regvalue, &pregister->lvds_mux_ctrl); +} + +void nx_disp_top_set_primary_mux(u32 sel) +{ + register struct nx_disp_top_register_set *pregister; + + pregister = __g_module_variables.pregister; + writel((u32)sel, &pregister->tftmpu_mux); +} + +void nx_disp_top_hdmi_set_vsync_start(u32 sel) +{ + register struct nx_disp_top_register_set *pregister; + + pregister = __g_module_variables.pregister; + writel((u32)sel, &pregister->hdmisyncctrl0); +} + +void nx_disp_top_hdmi_set_vsync_hsstart_end(u32 start, u32 end) +{ + register struct nx_disp_top_register_set *pregister; + + pregister = __g_module_variables.pregister; + writel((u32)(end << 16) | (start << 0), &pregister->hdmisyncctrl3); +} + +void nx_disp_top_hdmi_set_hactive_start(u32 sel) +{ + register struct nx_disp_top_register_set *pregister; + + pregister = __g_module_variables.pregister; + writel((u32)sel, &pregister->hdmisyncctrl1); +} + +void nx_disp_top_hdmi_set_hactive_end(u32 sel) +{ + register struct nx_disp_top_register_set *pregister; + + pregister = __g_module_variables.pregister; + writel((u32)sel, &pregister->hdmisyncctrl2); +} + +void nx_disp_top_set_hdmifield(u32 enable, u32 init_val, u32 vsynctoggle, + u32 hsynctoggle, u32 vsyncclr, u32 hsyncclr, + u32 field_use, u32 muxsel) +{ + register struct nx_disp_top_register_set *pregister; + u32 regvalue; + + pregister = __g_module_variables.pregister; + regvalue = ((enable & 0x01) << 0) | ((init_val & 0x01) << 1) | + ((vsynctoggle & 0x3fff) << 2) | + ((hsynctoggle & 0x3fff) << 17); + writel(regvalue, &pregister->hdmifieldctrl); + regvalue = ((field_use & 0x01) << 31) | ((muxsel & 0x01) << 30) | + ((hsyncclr) << 15) | ((vsyncclr) << 0); + writel(regvalue, &pregister->greg0); +} + +void nx_disp_top_set_padclock(u32 mux_index, u32 padclk_cfg) +{ + register struct nx_disp_top_register_set *pregister; + u32 regvalue; + + pregister = __g_module_variables.pregister; + regvalue = readl(&pregister->greg1); + if (padmux_secondary_mlc == mux_index) { + regvalue = regvalue & (~(0x7 << 3)); + regvalue = regvalue | (padclk_cfg << 3); + } else if (padmux_resolution_conv == mux_index) { + regvalue = regvalue & (~(0x7 << 6)); + regvalue = regvalue | (padclk_cfg << 6); + } else { + regvalue = regvalue & (~(0x7 << 0)); + regvalue = regvalue | (padclk_cfg << 0); + } + writel(regvalue, &pregister->greg1); +} + +void nx_disp_top_set_lcdif_enb(int enb) +{ + register struct nx_disp_top_register_set *pregister; + u32 regvalue; + + pregister = __g_module_variables.pregister; + regvalue = readl(&pregister->greg1); + regvalue = regvalue & (~(0x1 << 9)); + regvalue = regvalue | ((enb & 0x1) << 9); + writel(regvalue, &pregister->greg1); +} diff --git a/drivers/video/nexell/soc/s5pxx18_soc_disptop.h b/drivers/video/nexell/soc/s5pxx18_soc_disptop.h new file mode 100644 index 0000000000..c7bf5043e6 --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_disptop.h @@ -0,0 +1,385 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#ifndef _S5PXX18_SOC_DISPTOP_H_ +#define _S5PXX18_SOC_DISPTOP_H_ + +#include "s5pxx18_soc_disptype.h" + +#define NUMBER_OF_DISPTOP_MODULE 1 +#define PHY_BASEADDR_DISPLAYTOP_MODULE 0xC0100000 +#define PHY_BASEADDR_DISPTOP_LIST \ + { PHY_BASEADDR_DISPLAYTOP_MODULE } + +#define HDMI_ADDR_OFFSET \ + (((PHY_BASEADDR_DISPLAYTOP_MODULE / 0x00100000) % 2) ? 0x100000 \ + : 0x000000) +#define OTHER_ADDR_OFFSET \ + (((PHY_BASEADDR_DISPLAYTOP_MODULE / 0x00100000) % 2) ? 0x000000 \ + : 0x100000) +#define PHY_BASEADDR_DISPLAYTOP_MODULE_OFFSET (OTHER_ADDR_OFFSET + 0x001000) +#define PHY_BASEADDR_DUALDISPLAY_MODULE \ + (PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x002000) +#define PHY_BASEADDR_RESCONV_MODULE \ + (PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x003000) +#define PHY_BASEADDR_LCDINTERFACE_MODULE \ + (PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x004000) +#define PHY_BASEADDR_HDMI_MODULE (PHY_BASEADDR_DISPLAYTOP_MODULE + 0x000000) +#define PHY_BASEADDR_LVDS_MODULE \ + (PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x00a000) + +#define NUMBER_OF_DUALDISPLAY_MODULE 1 +#define INTNUM_OF_DUALDISPLAY_MODULE_PRIMIRQ \ + INTNUM_OF_DISPLAYTOP_MODULE_DUALDISPLAY_PRIMIRQ +#define INTNUM_OF_DUALDISPLAY_MODULE_SECONDIRQ \ + INTNUM_OF_DISPLAYTOP_MODULE_DUALDISPLAY_SECONDIRQ +#define RESETINDEX_OF_DUALDISPLAY_MODULE_I_NRST \ + RESETINDEX_OF_DISPLAYTOP_MODULE_I_DUALDISPLAY_NRST +#define PADINDEX_OF_DUALDISPLAY_O_NCS \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PADPRIMVCLK +#define PADINDEX_OF_DUALDISPLAY_O_NRD \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_HSYNC +#define PADINDEX_OF_DUALDISPLAY_O_RS \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_VSYNC +#define PADINDEX_OF_DUALDISPLAY_O_NWR \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADDE +#define PADINDEX_OF_DUALDISPLAY_PADPRIMVCLK \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PADPRIMVCLK +#define PADINDEX_OF_DUALDISPLAY_O_PRIM_PADN_HSYNC \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_HSYNC +#define PADINDEX_OF_DUALDISPLAY_O_PRIM_PADN_VSYNC \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_VSYNC +#define PADINDEX_OF_DUALDISPLAY_O_PRIM_PADDE \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADDE +#define PADINDEX_OF_DUALDISPLAY_PRIM_0_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_0_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_1_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_1_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_2_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_2_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_3_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_3_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_4_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_4_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_5_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_5_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_6_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_6_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_7_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_7_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_8_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_8_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_9_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_9_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_10_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_10_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_11_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_11_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_12_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_12_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_13_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_13_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_14_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_14_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_15_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_15_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_16_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_16_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_17_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_17_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_18_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_18_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_19_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_19_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_20_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_20_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_21_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_21_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_22_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_22_ +#define PADINDEX_OF_DUALDISPLAY_PRIM_23_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_23_ +#define PADINDEX_OF_DUALDISPLAY_PADSECONDVCLK \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PADPRIMVCLK +#define PADINDEX_OF_DUALDISPLAY_O_SECOND_PADN_HSYNC \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_HSYNC +#define PADINDEX_OF_DUALDISPLAY_O_SECOND_PADN_VSYNC \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_VSYNC +#define PADINDEX_OF_DUALDISPLAY_O_SECOND_PADDE \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADDE +#define PADINDEX_OF_DUALDISPLAY_SECOND_0_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_0_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_1_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_1_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_2_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_2_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_3_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_3_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_4_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_4_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_5_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_5_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_6_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_6_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_7_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_7_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_8_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_8_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_9_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_9_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_10_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_10_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_11_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_11_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_12_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_12_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_13_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_13_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_14_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_14_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_15_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_15_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_16_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_16_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_17_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_17_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_18_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_18_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_19_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_19_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_20_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_20_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_21_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_21_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_22_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_22_ +#define PADINDEX_OF_DUALDISPLAY_SECOND_23_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_23_ + +#define NUMBER_OF_RESCONV_MODULE 1 +#define INTNUM_OF_RESCONV_MODULE INTNUM_OF_DISPLAYTOP_MODULE_RESCONV_IRQ +#define RESETINDEX_OF_RESCONV_MODULE_I_NRST \ + RESETINDEX_OF_DISPLAYTOP_MODULE_I_RESCONV_NRST +#define RESETINDEX_OF_RESCONV_MODULE RESETINDEX_OF_RESCONV_MODULE_I_NRST +#define NUMBER_OF_LCDINTERFACE_MODULE 1 +#define RESETINDEX_OF_LCDINTERFACE_MODULE_I_NRST \ + RESETINDEX_OF_DISPLAYTOP_MODULE_I_LCDIF_NRST +#define PADINDEX_OF_LCDINTERFACE_O_VCLK \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PADPRIMVCLK +#define PADINDEX_OF_LCDINTERFACE_O_NHSYNC \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_HSYNC +#define PADINDEX_OF_LCDINTERFACE_O_NVSYNC \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_VSYNC +#define PADINDEX_OF_LCDINTERFACE_O_DE \ + PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADDE +#define PADINDEX_OF_LCDINTERFACE_RGB24_0_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_0_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_1_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_1_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_2_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_2_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_3_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_3_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_4_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_4_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_5_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_5_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_6_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_6_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_7_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_7_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_8_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_8_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_9_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_9_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_10_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_10_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_11_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_11_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_12_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_12_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_13_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_13_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_14_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_14_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_15_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_15_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_16_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_16_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_17_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_17_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_18_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_18_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_19_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_19_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_20_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_20_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_21_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_21_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_22_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_22_ +#define PADINDEX_OF_LCDINTERFACE_RGB24_23_ \ + PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_23_ + +#define NUMBER_OF_HDMI_MODULE 1 +#define INTNUM_OF_HDMI_MODULE INTNUM_OF_DISPLAYTOP_MODULE_HDMI_IRQ +#define RESETINDEX_OF_HDMI_MODULE_I_NRST \ + RESETINDEX_OF_DISPLAYTOP_MODULE_I_HDMI_NRST +#define RESETINDEX_OF_HDMI_MODULE_I_NRST_VIDEO \ + RESETINDEX_OF_DISPLAYTOP_MODULE_I_HDMI_VIDEO_NRST +#define RESETINDEX_OF_HDMI_MODULE_I_NRST_SPDIF \ + RESETINDEX_OF_DISPLAYTOP_MODULE_I_HDMI_SPDIF_NRST +#define RESETINDEX_OF_HDMI_MODULE_I_NRST_TMDS \ + RESETINDEX_OF_DISPLAYTOP_MODULE_I_HDMI_TMDS_NRST +#define RESETINDEX_OF_HDMI_MODULE_I_NRST_PHY \ + RESETINDEX_OF_DISPLAYTOP_MODULE_I_HDMI_PHY_NRST +#define PADINDEX_OF_HDMI_I_PHY_CLKI PADINDEX_OF_DISPLAYTOP_I_HDMI_CLKI +#define PADINDEX_OF_HDMI_O_PHY_CLKO PADINDEX_OF_DISPLAYTOP_O_HDMI_CLKO +#define PADINDEX_OF_HDMI_IO_PHY_REXT PADINDEX_OF_DISPLAYTOP_IO_HDMI_REXT +#define PADINDEX_OF_HDMI_O_PHY_TX0P PADINDEX_OF_DISPLAYTOP_O_HDMI_TX0P +#define PADINDEX_OF_HDMI_O_PHY_TX0N PADINDEX_OF_DISPLAYTOP_O_HDMI_TX0N +#define PADINDEX_OF_HDMI_O_PHY_TX1P PADINDEX_OF_DISPLAYTOP_O_HDMI_TX1P +#define PADINDEX_OF_HDMI_O_PHY_TX1N PADINDEX_OF_DISPLAYTOP_O_HDMI_TX1N +#define PADINDEX_OF_HDMI_O_PHY_TX2P PADINDEX_OF_DISPLAYTOP_O_HDMI_TX2P +#define PADINDEX_OF_HDMI_O_PHY_TX2N PADINDEX_OF_DISPLAYTOP_O_HDMI_TX2N +#define PADINDEX_OF_HDMI_O_PHY_TXCP PADINDEX_OF_DISPLAYTOP_O_HDMI_TXCP +#define PADINDEX_OF_HDMI_O_PHY_TXCN PADINDEX_OF_DISPLAYTOP_O_HDMI_TXCN +#define PADINDEX_OF_HDMI_I_HOTPLUG PADINDEX_OF_DISPLAYTOP_I_HDMI_HOTPLUG_5V +#define PADINDEX_OF_HDMI_IO_PAD_CEC PADINDEX_OF_DISPLAYTOP_IO_HDMI_CEC +#define NUMBER_OF_LVDS_MODULE 1 + +#define RESETINDEX_OF_LVDS_MODULE_I_RESETN \ + RESETINDEX_OF_DISPLAYTOP_MODULE_I_LVDS_NRST +#define RESETINDEX_OF_LVDS_MODULE RESETINDEX_OF_LVDS_MODULE_I_RESETN + +#define PADINDEX_OF_LVDS_TAP PADINDEX_OF_DISPLAYTOP_LVDS_TXP_A +#define PADINDEX_OF_LVDS_TAN PADINDEX_OF_DISPLAYTOP_LVDS_TXN_A +#define PADINDEX_OF_LVDS_TBP PADINDEX_OF_DISPLAYTOP_LVDS_TXP_B +#define PADINDEX_OF_LVDS_TBN PADINDEX_OF_DISPLAYTOP_LVDS_TXN_B +#define PADINDEX_OF_LVDS_TCP PADINDEX_OF_DISPLAYTOP_LVDS_TXP_C +#define PADINDEX_OF_LVDS_TCN PADINDEX_OF_DISPLAYTOP_LVDS_TXN_C +#define PADINDEX_OF_LVDS_TDP PADINDEX_OF_DISPLAYTOP_LVDS_TXP_D +#define PADINDEX_OF_LVDS_TDN PADINDEX_OF_DISPLAYTOP_LVDS_TXN_D +#define PADINDEX_OF_LVDS_TCLKP PADINDEX_OF_DISPLAYTOP_LVDS_TXP_CLK +#define PADINDEX_OF_LVDS_TCLKN PADINDEX_OF_DISPLAYTOP_LVDS_TXN_CLK +#define PADINDEX_OF_LVDS_ROUT PADINDEX_OF_DISPLAYTOP_LVDS_ROUT +#define PADINDEX_OF_LVDS_TEP PADINDEX_OF_DISPLAYTOP_LVDS_TXN_E +#define PADINDEX_OF_LVDS_TEN PADINDEX_OF_DISPLAYTOP_LVDS_TXN_E +#define NUMBER_OF_DISPTOP_CLKGEN_MODULE 5 + +enum disptop_clkgen_module_index { + res_conv_clkgen = 0, + lcdif_clkgen = 1, + to_mipi_clkgen = 2, + to_lvds_clkgen = 3, + hdmi_clkgen = 4, +}; + +enum disptop_res_conv_iclk_cclk { + res_conv_iclk = 0, + res_conv_cclk = 1, +}; + +enum disptop_res_conv_oclk { + res_conv_oclk = 1, +}; + +enum disptop_lcdif_clk { + lcdif_pixel_clkx_n = 0, + lcdif_pixel_clk = 1, +}; + +#define HDMI_SPDIF_CLKGEN 2 +#define HDMI_SPDIF_CLKOUT 0 +#define HDMI_I_VCLK_CLKOUT 0 +#define PHY_BASEADDR_DISPTOP_CLKGEN0_MODULE \ + (PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x006000) +#define PHY_BASEADDR_DISPTOP_CLKGEN1_MODULE \ + (PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x007000) +#define PHY_BASEADDR_DISPTOP_CLKGEN2_MODULE \ + (PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x005000) +#define PHY_BASEADDR_DISPTOP_CLKGEN3_MODULE \ + (PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x008000) +#define PHY_BASEADDR_DISPTOP_CLKGEN4_MODULE \ + (PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x009000) + +struct nx_disp_top_register_set { + u32 resconv_mux_ctrl; + u32 interconv_mux_ctrl; + u32 mipi_mux_ctrl; + u32 lvds_mux_ctrl; + u32 hdmifixctrl0; + u32 hdmisyncctrl0; + u32 hdmisyncctrl1; + u32 hdmisyncctrl2; + u32 hdmisyncctrl3; + u32 tftmpu_mux; + u32 hdmifieldctrl; + u32 greg0; + u32 greg1; + u32 greg2; + u32 greg3; + u32 greg4; + u32 greg5; +}; + +int nx_disp_top_initialize(void); +u32 nx_disp_top_get_number_of_module(void); + +u32 nx_disp_top_get_physical_address(void); +u32 nx_disp_top_get_size_of_register_set(void); +void nx_disp_top_set_base_address(void *base_address); +void *nx_disp_top_get_base_address(void); +int nx_disp_top_open_module(void); +int nx_disp_top_close_module(void); +int nx_disp_top_check_busy(void); + +enum mux_index { + primary_mlc = 0, + secondary_mlc = 1, + resolution_conv = 2, +}; + +enum prim_pad_mux_index { + padmux_primary_mlc = 0, + padmux_primary_mpu = 1, + padmux_secondary_mlc = 2, + padmux_resolution_conv = 3, +}; + +void nx_disp_top_set_resconvmux(int benb, u32 sel); +void nx_disp_top_set_hdmimux(int benb, u32 sel); +void nx_disp_top_set_mipimux(int benb, u32 sel); +void nx_disp_top_set_lvdsmux(int benb, u32 sel); +void nx_disp_top_set_primary_mux(u32 sel); +void nx_disp_top_hdmi_set_vsync_start(u32 sel); +void nx_disp_top_hdmi_set_vsync_hsstart_end(u32 start, u32 end); +void nx_disp_top_hdmi_set_hactive_start(u32 sel); +void nx_disp_top_hdmi_set_hactive_end(u32 sel); + +void nx_disp_top_set_hdmifield(u32 enable, u32 init_val, u32 vsynctoggle, + u32 hsynctoggle, u32 vsyncclr, u32 hsyncclr, + u32 field_use, u32 muxsel); + +enum padclk_config { + padclk_clk = 0, + padclk_inv_clk = 1, + padclk_reserved_clk = 2, + padclk_reserved_inv_clk = 3, + padclk_clk_div2_0 = 4, + padclk_clk_div2_90 = 5, + padclk_clk_div2_180 = 6, + padclk_clk_div2_270 = 7, +}; + +void nx_disp_top_set_padclock(u32 mux_index, u32 padclk_cfg); +void nx_disp_top_set_lcdif_enb(int enb); +void nx_disp_top_set_hdmifield(u32 enable, u32 init_val, u32 vsynctoggle, + u32 hsynctoggle, u32 vsyncclr, u32 hsyncclr, + u32 field_use, u32 muxsel); + +#endif diff --git a/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c b/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c new file mode 100644 index 0000000000..02361ba411 --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#include <linux/types.h> +#include <linux/io.h> + +#include "s5pxx18_soc_disptop_clk.h" +#include "s5pxx18_soc_disptop.h" + +static struct { + struct nx_disptop_clkgen_register_set *__g_pregister; +} __g_module_variables[NUMBER_OF_DISPTOP_CLKGEN_MODULE] = { + { NULL,}, +}; + +int nx_disp_top_clkgen_initialize(void) +{ + static int binit; + u32 i; + + if (binit == 0) { + for (i = 0; i < NUMBER_OF_DISPTOP_CLKGEN_MODULE; i++) + __g_module_variables[i].__g_pregister = NULL; + binit = 1; + } + return 1; +} + +u32 nx_disp_top_clkgen_get_number_of_module(void) +{ + return NUMBER_OF_DISPTOP_CLKGEN_MODULE; +} + +u32 nx_disp_top_clkgen_get_physical_address(u32 module_index) +{ + static const u32 physical_addr[] = + PHY_BASEADDR_DISPTOP_CLKGEN_LIST; + + return (u32)physical_addr[module_index]; +} + +u32 nx_disp_top_clkgen_get_size_of_register_set(void) +{ + return sizeof(struct nx_disptop_clkgen_register_set); +} + +void nx_disp_top_clkgen_set_base_address(u32 module_index, void *base_address) +{ + __g_module_variables[module_index].__g_pregister = + (struct nx_disptop_clkgen_register_set *)base_address; +} + +void *nx_disp_top_clkgen_get_base_address(u32 module_index) +{ + return (void *)__g_module_variables[module_index].__g_pregister; +} + +void nx_disp_top_clkgen_set_clock_bclk_mode(u32 module_index, + enum nx_bclkmode mode) +{ + register struct nx_disptop_clkgen_register_set *pregister; + register u32 regvalue; + u32 clkmode = 0; + + pregister = __g_module_variables[module_index].__g_pregister; + switch (mode) { + case nx_bclkmode_disable: + clkmode = 0; + case nx_bclkmode_dynamic: + clkmode = 2; + break; + case nx_bclkmode_always: + clkmode = 3; + break; + default: + break; + } + + regvalue = pregister->clkenb; + regvalue &= ~3ul; + regvalue |= (clkmode & 0x03); + + writel(regvalue, &pregister->clkenb); +} + +enum nx_bclkmode nx_disp_top_clkgen_get_clock_bclk_mode(u32 module_index) +{ + register struct nx_disptop_clkgen_register_set *pregister; + u32 mode = 0; + + pregister = __g_module_variables[module_index].__g_pregister; + mode = (pregister->clkenb & 3ul); + + switch (mode) { + case 0: + return nx_bclkmode_disable; + case 2: + return nx_bclkmode_dynamic; + case 3: + return nx_bclkmode_always; + default: + break; + } + return nx_bclkmode_disable; +} + +void nx_disp_top_clkgen_set_clock_pclk_mode(u32 module_index, + enum nx_pclkmode mode) +{ + register struct nx_disptop_clkgen_register_set *pregister; + register u32 regvalue; + const u32 pclkmode_pos = 3; + u32 clkmode = 0; + + pregister = __g_module_variables[module_index].__g_pregister; + switch (mode) { + case nx_pclkmode_dynamic: + clkmode = 0; + break; + case nx_pclkmode_always: + clkmode = 1; + break; + default: + break; + } + + regvalue = pregister->clkenb; + regvalue &= ~(1ul << pclkmode_pos); + regvalue |= (clkmode & 0x01) << pclkmode_pos; + + writel(regvalue, &pregister->clkenb); +} + +enum nx_pclkmode nx_disp_top_clkgen_get_clock_pclk_mode(u32 module_index) +{ + register struct nx_disptop_clkgen_register_set *pregister; + const u32 pclkmode_pos = 3; + + pregister = __g_module_variables[module_index].__g_pregister; + + if (pregister->clkenb & (1ul << pclkmode_pos)) + return nx_pclkmode_always; + + return nx_pclkmode_dynamic; +} + +void nx_disp_top_clkgen_set_clock_source(u32 module_index, u32 index, + u32 clk_src) +{ + register struct nx_disptop_clkgen_register_set *pregister; + register u32 read_value; + + const u32 clksrcsel_pos = 2; + const u32 clksrcsel_mask = 0x07 << clksrcsel_pos; + + pregister = __g_module_variables[module_index].__g_pregister; + + read_value = pregister->CLKGEN[index << 1]; + read_value &= ~clksrcsel_mask; + read_value |= clk_src << clksrcsel_pos; + + writel(read_value, &pregister->CLKGEN[index << 1]); +} + +u32 nx_disp_top_clkgen_get_clock_source(u32 module_index, u32 index) +{ + register struct nx_disptop_clkgen_register_set *pregister; + const u32 clksrcsel_pos = 2; + const u32 clksrcsel_mask = 0x07 << clksrcsel_pos; + + pregister = __g_module_variables[module_index].__g_pregister; + + return (pregister->CLKGEN[index << 1] & + clksrcsel_mask) >> clksrcsel_pos; +} + +void nx_disp_top_clkgen_set_clock_divisor(u32 module_index, u32 index, + u32 divisor) +{ + register struct nx_disptop_clkgen_register_set *pregister; + const u32 clkdiv_pos = 5; + const u32 clkdiv_mask = 0xff << clkdiv_pos; + register u32 read_value; + + pregister = __g_module_variables[module_index].__g_pregister; + + read_value = pregister->CLKGEN[index << 1]; + read_value &= ~clkdiv_mask; + read_value |= (divisor - 1) << clkdiv_pos; + writel(read_value, &pregister->CLKGEN[index << 1]); +} + +u32 nx_disp_top_clkgen_get_clock_divisor(u32 module_index, u32 index) +{ + register struct nx_disptop_clkgen_register_set *pregister; + const u32 clkdiv_pos = 5; + const u32 clkdiv_mask = 0xff << clkdiv_pos; + + pregister = __g_module_variables[module_index].__g_pregister; + + return ((pregister->CLKGEN[index << 1] & + clkdiv_mask) >> clkdiv_pos) + 1; +} + +void nx_disp_top_clkgen_set_clock_divisor_enable(u32 module_index, int enable) +{ + register struct nx_disptop_clkgen_register_set *pregister; + register u32 read_value; + const u32 clkgenenb_pos = 2; + const u32 clkgenenb_mask = 1ul << clkgenenb_pos; + + pregister = __g_module_variables[module_index].__g_pregister; + + read_value = pregister->clkenb; + read_value &= ~clkgenenb_mask; + read_value |= (u32)enable << clkgenenb_pos; + + writel(read_value, &pregister->clkenb); +} + +int nx_disp_top_clkgen_get_clock_divisor_enable(u32 module_index) +{ + register struct nx_disptop_clkgen_register_set *pregister; + const u32 clkgenenb_pos = 2; + const u32 clkgenenb_mask = 1ul << clkgenenb_pos; + + pregister = __g_module_variables[module_index].__g_pregister; + + return (int)((pregister->clkenb & + clkgenenb_mask) >> clkgenenb_pos); +} + +void nx_disp_top_clkgen_set_clock_out_inv(u32 module_index, u32 index, + int out_clk_inv) +{ + register struct nx_disptop_clkgen_register_set *pregister; + register u32 read_value; + const u32 outclkinv_pos = 1; + const u32 outclkinv_mask = 1ul << outclkinv_pos; + + pregister = __g_module_variables[module_index].__g_pregister; + + read_value = pregister->CLKGEN[index << 1]; + read_value &= ~outclkinv_mask; + read_value |= out_clk_inv << outclkinv_pos; + + writel(read_value, &pregister->CLKGEN[index << 1]); +} + +int nx_disp_top_clkgen_get_clock_out_inv(u32 module_index, u32 index) +{ + register struct nx_disptop_clkgen_register_set *pregister; + const u32 outclkinv_pos = 1; + const u32 outclkinv_mask = 1ul << outclkinv_pos; + + pregister = __g_module_variables[module_index].__g_pregister; + + return (int)((pregister->CLKGEN[index << 1] & + outclkinv_mask) >> outclkinv_pos); +} + +int nx_disp_top_clkgen_set_input_inv(u32 module_index, + u32 index, int in_clk_inv) +{ + register struct nx_disptop_clkgen_register_set *pregister; + register u32 read_value; + const u32 inclkinv_pos = 4 + index; + const u32 inclkinv_mask = 1ul << inclkinv_pos; + + pregister = __g_module_variables[module_index].__g_pregister; + + read_value = pregister->clkenb; + read_value &= ~inclkinv_mask; + read_value |= in_clk_inv << inclkinv_pos; + + writel(read_value, &pregister->clkenb); + return true; +} + +int nx_disp_top_clkgen_get_input_inv(u32 module_index, u32 index) +{ + register struct nx_disptop_clkgen_register_set *pregister; + const u32 inclkinv_pos = 4 + index; + const u32 inclkinv_mask = 1ul << inclkinv_pos; + + pregister = __g_module_variables[module_index].__g_pregister; + + return (int)((pregister->clkenb & + inclkinv_mask) >> inclkinv_pos); +} + +void nx_disp_top_clkgen_set_clock_out_select(u32 module_index, u32 index, + int bbypass) +{ + register struct nx_disptop_clkgen_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].__g_pregister; + + read_value = pregister->CLKGEN[index << 1]; + read_value = read_value & (~0x01); + read_value = read_value | bbypass; + + writel(read_value, &pregister->CLKGEN[index << 1]); +} diff --git a/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.h b/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.h new file mode 100644 index 0000000000..d55fef7730 --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#ifndef _S5PXX18_SOC_DISPTOP_CLK_H_ +#define _S5PXX18_SOC_DISPTOP_CLK_H_ + +#include "s5pxx18_soc_disptype.h" + +#define PHY_BASEADDR_DISPTOP_CLKGEN_LIST \ + { PHY_BASEADDR_DISPTOP_CLKGEN0_MODULE, \ + PHY_BASEADDR_DISPTOP_CLKGEN1_MODULE, \ + PHY_BASEADDR_DISPTOP_CLKGEN2_MODULE, \ + PHY_BASEADDR_DISPTOP_CLKGEN3_MODULE, \ + PHY_BASEADDR_DISPTOP_CLKGEN4_MODULE, \ + } + +struct nx_disptop_clkgen_register_set { + u32 clkenb; + u32 CLKGEN[4]; +}; + +int nx_disp_top_clkgen_initialize(void); +u32 nx_disp_top_clkgen_get_number_of_module(void); +u32 nx_disp_top_clkgen_get_physical_address(u32 module_index); +u32 nx_disp_top_clkgen_get_size_of_register_set(void); +void nx_disp_top_clkgen_set_base_address(u32 module_index, + void *base_address); +void *nx_disp_top_clkgen_get_base_address(u32 module_index); +void nx_disp_top_clkgen_set_clock_pclk_mode(u32 module_index, + enum nx_pclkmode mode); +enum nx_pclkmode nx_disp_top_clkgen_get_clock_pclk_mode(u32 module_index); +void nx_disp_top_clkgen_set_clock_source(u32 module_index, u32 index, + u32 clk_src); +u32 nx_disp_top_clkgen_get_clock_source(u32 module_index, u32 index); +void nx_disp_top_clkgen_set_clock_divisor(u32 module_index, u32 index, + u32 divisor); +u32 nx_disp_top_clkgen_get_clock_divisor(u32 module_index, u32 index); +void nx_disp_top_clkgen_set_clock_divisor_enable(u32 module_index, + int enable); +int nx_disp_top_clkgen_get_clock_divisor_enable(u32 module_index); +void nx_disp_top_clkgen_set_clock_bclk_mode(u32 module_index, + enum nx_bclkmode mode); +enum nx_bclkmode nx_disp_top_clkgen_get_clock_bclk_mode(u32 module_index); + +void nx_disp_top_clkgen_set_clock_out_inv(u32 module_index, u32 index, + int out_clk_inv); +int nx_disp_top_clkgen_get_clock_out_inv(u32 module_index, u32 index); +int nx_disp_top_clkgen_set_input_inv(u32 module_index, u32 index, + int out_clk_inv); +int nx_disp_top_clkgen_get_input_inv(u32 module_index, u32 index); + +void nx_disp_top_clkgen_set_clock_out_select(u32 module_index, u32 index, + int bbypass); + +#endif diff --git a/drivers/video/nexell/soc/s5pxx18_soc_disptype.h b/drivers/video/nexell/soc/s5pxx18_soc_disptype.h new file mode 100644 index 0000000000..b5df7a7344 --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_disptype.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#ifndef _S5PXX18_SOC_DISP_TYPE_H_ +#define _S5PXX18_SOC_DISP_TYPE_H_ + +/* clock control types */ +enum nx_pclkmode { + nx_pclkmode_dynamic = 0UL, + nx_pclkmode_always = 1UL +}; + +enum nx_bclkmode { + nx_bclkmode_disable = 0UL, + nx_bclkmode_dynamic = 2UL, + nx_bclkmode_always = 3UL +}; + +#endif diff --git a/drivers/video/nexell/soc/s5pxx18_soc_dpc.c b/drivers/video/nexell/soc/s5pxx18_soc_dpc.c new file mode 100644 index 0000000000..fc15d6b4d0 --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_dpc.c @@ -0,0 +1,1569 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#include <linux/types.h> +#include <linux/io.h> + +#include "s5pxx18_soc_dpc.h" + +static struct { + struct nx_dpc_register_set *pregister; +} __g_module_variables[NUMBER_OF_DPC_MODULE] = { { NULL,},}; + +int nx_dpc_initialize(void) +{ + static int binit; + u32 i; + + if (binit == 0) { + for (i = 0; i < NUMBER_OF_DPC_MODULE; i++) + __g_module_variables[i].pregister = NULL; + binit = 1; + } + return 1; +} + +u32 nx_dpc_get_number_of_module(void) +{ + return NUMBER_OF_DPC_MODULE; +} + +u32 nx_dpc_get_physical_address(u32 module_index) +{ + const u32 physical_addr[] = PHY_BASEADDR_DPC_LIST; + + return physical_addr[module_index]; +} + +void nx_dpc_set_base_address(u32 module_index, void *base_address) +{ + __g_module_variables[module_index].pregister = + (struct nx_dpc_register_set *)base_address; +} + +void *nx_dpc_get_base_address(u32 module_index) +{ + return (void *)__g_module_variables[module_index].pregister; +} + +void nx_dpc_set_interrupt_enable(u32 module_index, int32_t int_num, int enable) +{ + const u32 intenb_pos = 11; + const u32 intenb_mask = 1ul << intenb_pos; + const u32 intpend_pos = 10; + const u32 intpend_mask = 1ul << intpend_pos; + + register u32 regvalue; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + regvalue = pregister->dpcctrl0; + regvalue &= ~(intenb_mask | intpend_mask); + regvalue |= (u32)enable << intenb_pos; + + writel(regvalue, &pregister->dpcctrl0); +} + +int nx_dpc_get_interrupt_enable(u32 module_index, int32_t int_num) +{ + const u32 intenb_pos = 11; + const u32 intenb_mask = 1ul << intenb_pos; + + return (int)((__g_module_variables[module_index].pregister->dpcctrl0 & + intenb_mask) >> intenb_pos); +} + +void nx_dpc_set_interrupt_enable32(u32 module_index, u32 enable_flag) +{ + const u32 intenb_pos = 11; + const u32 intenb_mask = 1 << intenb_pos; + const u32 intpend_pos = 10; + const u32 intpend_mask = 1 << intpend_pos; + + register struct nx_dpc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->dpcctrl0 & ~(intpend_mask | intenb_mask); + + writel((u32)(read_value | (enable_flag & 0x01) << intenb_pos), + &pregister->dpcctrl0); +} + +u32 nx_dpc_get_interrupt_enable32(u32 module_index) +{ + const u32 intenb_pos = 11; + const u32 intenb_mask = 1 << intenb_pos; + + return (u32)((__g_module_variables[module_index].pregister->dpcctrl0 & + intenb_mask) >> intenb_pos); +} + +int nx_dpc_get_interrupt_pending(u32 module_index, int32_t int_num) +{ + const u32 intpend_pos = 10; + const u32 intpend_mask = 1ul << intpend_pos; + + return (int)((__g_module_variables[module_index].pregister->dpcctrl0 & + intpend_mask) >> intpend_pos); +} + +u32 nx_dpc_get_interrupt_pending32(u32 module_index) +{ + const u32 intpend_pos = 10; + const u32 intpend_mask = 1 << intpend_pos; + + return (u32)((__g_module_variables[module_index].pregister->dpcctrl0 & + intpend_mask) >> intpend_pos); +} + +void nx_dpc_clear_interrupt_pending(u32 module_index, int32_t int_num) +{ + const u32 intpend_pos = 10; + register struct nx_dpc_register_set *pregister; + register u32 regvalue; + + pregister = __g_module_variables[module_index].pregister; + regvalue = pregister->dpcctrl0; + regvalue |= 1ul << intpend_pos; + + writel(regvalue, &pregister->dpcctrl0); +} + +void nx_dpc_clear_interrupt_pending32(u32 module_index, u32 pending_flag) +{ + const u32 intpend_pos = 10; + const u32 intpend_mask = 1 << intpend_pos; + register struct nx_dpc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->dpcctrl0 & ~intpend_mask; + + writel((u32)(read_value | ((pending_flag & 0x01) << intpend_pos)), + &pregister->dpcctrl0); +} + +void nx_dpc_set_interrupt_enable_all(u32 module_index, int enable) +{ + const u32 intenb_pos = 11; + const u32 intenb_mask = 1ul << intenb_pos; + const u32 intpend_pos = 10; + const u32 intpend_mask = 1ul << intpend_pos; + register u32 regvalue; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + regvalue = pregister->dpcctrl0; + regvalue &= ~(intenb_mask | intpend_mask); + regvalue |= (u32)enable << intenb_pos; + + writel(regvalue, &pregister->dpcctrl0); +} + +int nx_dpc_get_interrupt_enable_all(u32 module_index) +{ + const u32 intenb_pos = 11; + const u32 intenb_mask = 1ul << intenb_pos; + + return (int)((__g_module_variables[module_index].pregister->dpcctrl0 & + intenb_mask) >> intenb_pos); +} + +int nx_dpc_get_interrupt_pending_all(u32 module_index) +{ + const u32 intpend_pos = 10; + const u32 intpend_mask = 1ul << intpend_pos; + + return (int)((__g_module_variables[module_index].pregister->dpcctrl0 & + intpend_mask) >> intpend_pos); +} + +void nx_dpc_clear_interrupt_pending_all(u32 module_index) +{ + const u32 intpend_pos = 10; + register struct nx_dpc_register_set *pregister; + register u32 regvalue; + + pregister = __g_module_variables[module_index].pregister; + regvalue = pregister->dpcctrl0; + regvalue |= 1ul << intpend_pos; + + writel(regvalue, &pregister->dpcctrl0); +} + +int32_t nx_dpc_get_interrupt_pending_number(u32 module_index) +{ + const u32 intenb_pos = 11; + const u32 intpend_pos = 10; + register struct nx_dpc_register_set *pregister; + register u32 pend; + + pregister = __g_module_variables[module_index].pregister; + pend = ((pregister->dpcctrl0 >> intenb_pos) && + (pregister->dpcctrl0 >> intpend_pos)); + + if (pend & 0x01) + return 0; + + return -1; +} + +void nx_dpc_set_clock_pclk_mode(u32 module_index, enum nx_pclkmode mode) +{ + const u32 pclkmode_pos = 3; + register u32 regvalue; + register struct nx_dpc_register_set *pregister; + u32 clkmode = 0; + + pregister = __g_module_variables[module_index].pregister; + switch (mode) { + case nx_pclkmode_dynamic: + clkmode = 0; + break; + case nx_pclkmode_always: + clkmode = 1; + break; + default: + break; + } + regvalue = pregister->dpcclkenb; + regvalue &= ~(1ul << pclkmode_pos); + regvalue |= (clkmode & 0x01) << pclkmode_pos; + + writel(regvalue, &pregister->dpcclkenb); +} + +enum nx_pclkmode nx_dpc_get_clock_pclk_mode(u32 module_index) +{ + const u32 pclkmode_pos = 3; + + if (__g_module_variables[module_index].pregister->dpcclkenb & + (1ul << pclkmode_pos)) { + return nx_pclkmode_always; + } + return nx_pclkmode_dynamic; +} + +void nx_dpc_set_clock_source(u32 module_index, u32 index, u32 clk_src) +{ + const u32 clksrcsel_pos = 2; + const u32 clksrcsel_mask = 0x07 << clksrcsel_pos; + register struct nx_dpc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->dpcclkgen[index][0]; + read_value &= ~clksrcsel_mask; + read_value |= clk_src << clksrcsel_pos; + + writel(read_value, &pregister->dpcclkgen[index][0]); +} + +u32 nx_dpc_get_clock_source(u32 module_index, u32 index) +{ + const u32 clksrcsel_pos = 2; + const u32 clksrcsel_mask = 0x07 << clksrcsel_pos; + + return (__g_module_variables[module_index] + .pregister->dpcclkgen[index][0] & + clksrcsel_mask) >> clksrcsel_pos; +} + +void nx_dpc_set_clock_divisor(u32 module_index, u32 index, u32 divisor) +{ + const u32 clkdiv_pos = 5; + const u32 clkdiv_mask = ((1 << 8) - 1) << clkdiv_pos; + register struct nx_dpc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->dpcclkgen[index][0]; + read_value &= ~clkdiv_mask; + read_value |= (divisor - 1) << clkdiv_pos; + + writel(read_value, &pregister->dpcclkgen[index][0]); +} + +u32 nx_dpc_get_clock_divisor(u32 module_index, u32 index) +{ + const u32 clkdiv_pos = 5; + const u32 clkdiv_mask = ((1 << 8) - 1) << clkdiv_pos; + + return ((__g_module_variables[module_index] + .pregister->dpcclkgen[index][0] & + clkdiv_mask) >> clkdiv_pos) + 1; +} + +void nx_dpc_set_clock_out_inv(u32 module_index, u32 index, int out_clk_inv) +{ + const u32 outclkinv_pos = 1; + const u32 outclkinv_mask = 1ul << outclkinv_pos; + register struct nx_dpc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->dpcclkgen[index][0]; + read_value &= ~outclkinv_mask; + read_value |= out_clk_inv << outclkinv_pos; + + writel(read_value, &pregister->dpcclkgen[index][0]); +} + +int nx_dpc_get_clock_out_inv(u32 module_index, u32 index) +{ + const u32 outclkinv_pos = 1; + const u32 outclkinv_mask = 1ul << outclkinv_pos; + + return (int)((__g_module_variables[module_index] + .pregister->dpcclkgen[index][0] & + outclkinv_mask) >> outclkinv_pos); +} + +void nx_dpc_set_clock_out_select(u32 module_index, u32 index, int bbypass) +{ + const u32 outclksel_pos = 0; + const u32 outclksel_mask = 1ul << outclksel_pos; + register struct nx_dpc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->dpcclkgen[index][0]; + read_value &= ~outclksel_mask; + if (bbypass == 0) + read_value |= outclksel_mask; + + writel(read_value, &pregister->dpcclkgen[index][0]); +} + +int nx_dpc_get_clock_out_select(u32 module_index, u32 index) +{ + const u32 outclksel_pos = 0; + const u32 outclksel_mask = 1ul << outclksel_pos; + + if (__g_module_variables[module_index].pregister->dpcclkgen[index][0] & + outclksel_mask) { + return 0; + } else { + return 1; + } +} + +void nx_dpc_set_clock_polarity(u32 module_index, int bpolarity) +{ + const u32 clkpol_pos = 2; + const u32 clkpol_mask = 1ul << clkpol_pos; + register struct nx_dpc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->dpcctrl1; + read_value &= ~clkpol_mask; + if (bpolarity == 1) + read_value |= clkpol_mask; + + writel(read_value, &pregister->dpcctrl1); +} + +int nx_dpc_get_clock_polarity(u32 module_index) +{ + const u32 clkpol_pos = 2; + const u32 clkpol_mask = 1ul << clkpol_pos; + + if (__g_module_variables[module_index].pregister->dpcctrl1 & + clkpol_mask) { + return 1; + } else { + return 0; + } +} + +void nx_dpc_set_clock_out_enb(u32 module_index, u32 index, int out_clk_enb) +{ + const u32 outclkenb_pos = 15; + const u32 outclkenb_mask = 1ul << outclkenb_pos; + register struct nx_dpc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->dpcclkgen[index][0]; + read_value &= ~outclkenb_mask; + + if (out_clk_enb == 1) + read_value |= outclkenb_mask; + + writel(read_value, &pregister->dpcclkgen[index][0]); +} + +int nx_dpc_get_clock_out_enb(u32 module_index, u32 index) +{ + const u32 outclkenb_pos = 15; + const u32 outclkenb_mask = 1ul << outclkenb_pos; + + if (__g_module_variables[module_index].pregister->dpcclkgen[index][0] & + outclkenb_mask) { + return 1; + } else { + return 0; + } +} + +void nx_dpc_set_clock_out_delay(u32 module_index, u32 index, u32 delay) +{ + const u32 outclkdelay_pos = 0; + const u32 outclkdelay_mask = 0x1f << outclkdelay_pos; + register struct nx_dpc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->dpcclkgen[index][1]; + read_value &= ~outclkdelay_mask; + read_value |= (u32)delay << outclkdelay_pos; + + writel(read_value, &pregister->dpcclkgen[index][1]); +} + +u32 nx_dpc_get_clock_out_delay(u32 module_index, u32 index) +{ + register struct nx_dpc_register_set *pregister; + const u32 outclkdelay_pos = 0; + const u32 outclkdelay_mask = 0x1f << outclkdelay_pos; + + pregister = __g_module_variables[module_index].pregister; + + return (u32)((pregister->dpcclkgen[index][1] & outclkdelay_mask) >> + outclkdelay_pos); +} + +void nx_dpc_set_clock_divisor_enable(u32 module_index, int enable) +{ + const u32 clkgenenb_pos = 2; + const u32 clkgenenb_mask = 1ul << clkgenenb_pos; + register struct nx_dpc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->dpcclkenb; + read_value &= ~clkgenenb_mask; + read_value |= (u32)enable << clkgenenb_pos; + + writel(read_value, &pregister->dpcclkenb); +} + +int nx_dpc_get_clock_divisor_enable(u32 module_index) +{ + const u32 clkgenenb_pos = 2; + const u32 clkgenenb_mask = 1ul << clkgenenb_pos; + + return (int)((__g_module_variables[module_index].pregister->dpcclkenb & + clkgenenb_mask) >> clkgenenb_pos); +} + +void nx_dpc_set_dpc_enable(u32 module_index, int benb) +{ + const u32 intpend_pos = 10; + const u32 intpend_mask = 1ul << intpend_pos; + const u32 dpcenb_pos = 15; + const u32 dpcenb_mask = 1ul << dpcenb_pos; + register struct nx_dpc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->dpcctrl0; + read_value &= ~(intpend_mask | dpcenb_mask); + read_value |= (u32)benb << dpcenb_pos; + + writel(read_value, &pregister->dpcctrl0); +} + +int nx_dpc_get_dpc_enable(u32 module_index) +{ + const u32 dpcenb_pos = 15; + const u32 dpcenb_mask = 1ul << dpcenb_pos; + + return (int)((__g_module_variables[module_index].pregister->dpcctrl0 & + dpcenb_mask) >> dpcenb_pos); +} + +void nx_dpc_set_delay(u32 module_index, u32 delay_rgb_pvd, u32 delay_hs_cp1, + u32 delay_vs_fram, u32 delay_de_cp2) +{ + const u32 intpend_mask = 1u << 10; + const u32 delayrgb_pos = 4; + const u32 delayrgb_mask = 0xfu << delayrgb_pos; + register u32 temp; + const u32 delayde_pos = 0; + const u32 delayvs_pos = 8; + const u32 delayhs_pos = 0; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + temp = pregister->dpcctrl0; + temp &= (u32)~(intpend_mask | delayrgb_mask); + temp = (u32)(temp | (delay_rgb_pvd << delayrgb_pos)); + + writel(temp, &pregister->dpcctrl0); + + writel((u32)((delay_vs_fram << delayvs_pos) | + (delay_hs_cp1 << delayhs_pos)), &pregister->dpcdelay0); + + writel((u32)(delay_de_cp2 << delayde_pos), &pregister->dpcdelay1); +} + +void nx_dpc_get_delay(u32 module_index, u32 *pdelayrgb_pvd, u32 *pdelayhs_cp1, + u32 *pdelayvs_fram, u32 *pdelayde_cp2) +{ + const u32 delayrgb_pos = 4; + const u32 delayrgb_mask = 0xfu << delayrgb_pos; + const u32 delayde_pos = 0; + const u32 delayde_mask = 0x3fu << delayde_pos; + const u32 delayvs_pos = 8; + const u32 delayvs_mask = 0x3fu << delayvs_pos; + const u32 delayhs_pos = 0; + const u32 delayhs_mask = 0x3fu << delayhs_pos; + register u32 temp; + + temp = __g_module_variables[module_index].pregister->dpcctrl0; + if (pdelayrgb_pvd) + *pdelayrgb_pvd = (u32)((temp & delayrgb_mask) >> delayrgb_pos); + temp = __g_module_variables[module_index].pregister->dpcdelay0; + if (pdelayhs_cp1) + *pdelayhs_cp1 = (u32)((temp & delayhs_mask) >> delayhs_pos); + if (pdelayvs_fram) + *pdelayvs_fram = (u32)((temp & delayvs_mask) >> delayvs_pos); + temp = __g_module_variables[module_index].pregister->dpcdelay1; + if (pdelayde_cp2) + *pdelayde_cp2 = (u32)((temp & delayde_mask) >> delayde_pos); +} + +void nx_dpc_set_dither(u32 module_index, enum nx_dpc_dither dither_r, + enum nx_dpc_dither dither_g, enum nx_dpc_dither dither_b) +{ + const u32 dither_mask = 0x3fu; + const u32 rdither_pos = 0; + const u32 gdither_pos = 2; + const u32 bdither_pos = 4; + register u32 temp; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + temp = pregister->dpcctrl1; + temp &= (u32)~dither_mask; + temp = (u32)(temp | + ((dither_b << bdither_pos) | (dither_g << gdither_pos) | + (dither_r << rdither_pos))); + + writel(temp, &pregister->dpcctrl1); +} + +void nx_dpc_get_dither(u32 module_index, enum nx_dpc_dither *pditherr, + enum nx_dpc_dither *pditherg, + enum nx_dpc_dither *pditherb) +{ + const u32 rdither_pos = 0; + const u32 rdither_mask = 0x3u << rdither_pos; + const u32 gdither_pos = 2; + const u32 gdither_mask = 0x3u << gdither_pos; + const u32 bdither_pos = 4; + const u32 bdither_mask = 0x3u << bdither_pos; + register u32 temp; + + temp = __g_module_variables[module_index].pregister->dpcctrl1; + if (pditherr) + *pditherr = + (enum nx_dpc_dither)((temp & rdither_mask) >> rdither_pos); + if (pditherg) + *pditherg = + (enum nx_dpc_dither)((temp & gdither_mask) >> gdither_pos); + if (pditherb) + *pditherb = + (enum nx_dpc_dither)((temp & bdither_mask) >> bdither_pos); +} + +void nx_dpc_set_mode(u32 module_index, enum nx_dpc_format format, + int binterlace, int binvertfield, int brgbmode, + int bswaprb, enum nx_dpc_ycorder ycorder, int bclipyc, + int bembeddedsync, enum nx_dpc_padclk clock, + int binvertclock, int bdualview) +{ + const u32 polfield_pos = 2; + const u32 seavenb_pos = 8; + const u32 scanmode_pos = 9; + const u32 intpend_pos = 10; + const u32 rgbmode_pos = 12; + + const u32 dither_mask = 0x3f; + const u32 ycorder_pos = 6; + const u32 format_pos = 8; + const u32 ycrange_pos = 13; + const u32 swaprb_pos = 15; + + const u32 padclksel_pos = 0; + const u32 padclksel_mask = 3u << padclksel_pos; + const u32 lcdtype_pos = 7; + const u32 lcdtype_mask = 3u << lcdtype_pos; + register struct nx_dpc_register_set *pregister; + register u32 temp; + + pregister = __g_module_variables[module_index].pregister; + temp = pregister->dpcctrl0; + temp &= (u32)~(1u << intpend_pos); + if (binterlace) + temp |= (u32)(1u << scanmode_pos); + else + temp &= (u32)~(1u << scanmode_pos); + if (binvertfield) + temp |= (u32)(1u << polfield_pos); + else + temp &= (u32)~(1u << polfield_pos); + if (brgbmode) + temp |= (u32)(1u << rgbmode_pos); + else + temp &= (u32)~(1u << rgbmode_pos); + if (bembeddedsync) + temp |= (u32)(1u << seavenb_pos); + else + temp &= (u32)~(1u << seavenb_pos); + + writel(temp, &pregister->dpcctrl0); + temp = pregister->dpcctrl1; + temp &= (u32)dither_mask; + temp = (u32)(temp | (ycorder << ycorder_pos)); + if (format >= 16) { + register u32 temp1; + + temp1 = pregister->dpcctrl2; + temp1 = temp1 | (1 << 4); + writel(temp1, &pregister->dpcctrl2); + } else { + register u32 temp1; + + temp1 = pregister->dpcctrl2; + temp1 = temp1 & ~(1 << 4); + writel(temp1, &pregister->dpcctrl2); + } + temp = (u32)(temp | ((format & 0xf) << format_pos)); + if (!bclipyc) + temp |= (u32)(1u << ycrange_pos); + if (bswaprb) + temp |= (u32)(1u << swaprb_pos); + + writel(temp, &pregister->dpcctrl1); + temp = pregister->dpcctrl2; + temp &= (u32)~(padclksel_mask | lcdtype_mask); + temp = (u32)(temp | (clock << padclksel_pos)); + + writel(temp, &pregister->dpcctrl2); + + nx_dpc_set_clock_out_inv(module_index, 0, binvertclock); + nx_dpc_set_clock_out_inv(module_index, 1, binvertclock); +} + +void nx_dpc_get_mode(u32 module_index, enum nx_dpc_format *pformat, + int *pbinterlace, int *pbinvertfield, int *pbrgbmode, + int *pbswaprb, enum nx_dpc_ycorder *pycorder, + int *pbclipyc, int *pbembeddedsync, + enum nx_dpc_padclk *pclock, int *pbinvertclock, + int *pbdualview) +{ + const u32 polfield = 1u << 2; + const u32 seavenb = 1u << 8; + const u32 scanmode = 1u << 9; + const u32 rgbmode = 1u << 12; + + const u32 ycorder_pos = 6; + const u32 ycorder_mask = 0x3u << ycorder_pos; + const u32 format_pos = 8; + const u32 format_mask = 0xfu << format_pos; + const u32 ycrange = 1u << 13; + const u32 swaprb = 1u << 15; + + const u32 padclksel_pos = 0; + const u32 padclksel_mask = 3u << padclksel_pos; + const u32 lcdtype_pos = 7; + const u32 lcdtype_mask = 3u << lcdtype_pos; + register u32 temp; + + temp = __g_module_variables[module_index].pregister->dpcctrl0; + if (pbinterlace) + *pbinterlace = (temp & scanmode) ? 1 : 0; + + if (pbinvertfield) + *pbinvertfield = (temp & polfield) ? 1 : 0; + + if (pbrgbmode) + *pbrgbmode = (temp & rgbmode) ? 1 : 0; + + if (pbembeddedsync) + *pbembeddedsync = (temp & seavenb) ? 1 : 0; + + temp = __g_module_variables[module_index].pregister->dpcctrl1; + + if (pycorder) + *pycorder = + (enum nx_dpc_ycorder)((temp & ycorder_mask) >> ycorder_pos); + + if (pformat) + *pformat = + (enum nx_dpc_format)((temp & format_mask) >> format_pos); + if (pbclipyc) + *pbclipyc = (temp & ycrange) ? 0 : 1; + if (pbswaprb) + *pbswaprb = (temp & swaprb) ? 1 : 0; + + temp = __g_module_variables[module_index].pregister->dpcctrl2; + + if (pclock) + *pclock = + (enum nx_dpc_padclk)((temp & padclksel_mask) >> + padclksel_pos); + + if (pbdualview) + *pbdualview = (2 == ((temp & lcdtype_mask) >> lcdtype_pos)) + ? 1 : 0; + + if (pbinvertclock) + *pbinvertclock = nx_dpc_get_clock_out_inv(module_index, 1); +} + +void nx_dpc_set_hsync(u32 module_index, u32 avwidth, u32 hsw, u32 hfp, u32 hbp, + int binvhsync) +{ + const u32 intpend = 1u << 10; + const u32 polhsync = 1u << 0; + register u32 temp; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + writel((u32)(hsw + hbp + avwidth + hfp - 1), &pregister->dpchtotal); + + writel((u32)(hsw - 1), &pregister->dpchswidth); + + writel((u32)(hsw + hbp - 1), &pregister->dpchastart); + + writel((u32)(hsw + hbp + avwidth - 1), &pregister->dpchaend); + temp = pregister->dpcctrl0; + temp &= ~intpend; + if (binvhsync) + temp |= (u32)polhsync; + else + temp &= (u32)~polhsync; + + writel(temp, &pregister->dpcctrl0); +} + +void nx_dpc_get_hsync(u32 module_index, u32 *pavwidth, u32 *phsw, u32 *phfp, + u32 *phbp, int *pbinvhsync) +{ + const u32 polhsync = 1u << 0; + u32 htotal, hsw, hab, hae; + u32 avw, hfp, hbp; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + htotal = (u32)pregister->dpchtotal + 1; + hsw = (u32)pregister->dpchswidth + 1; + hab = (u32)pregister->dpchastart + 1; + hae = (u32)pregister->dpchaend + 1; + hbp = hab - hsw; + avw = hae - hab; + hfp = htotal - hae; + if (pavwidth) + *pavwidth = avw; + if (phsw) + *phsw = hsw; + if (phfp) + *phfp = hfp; + if (phbp) + *phbp = hbp; + if (pbinvhsync) + *pbinvhsync = (pregister->dpcctrl0 & polhsync) ? 1 : 0; +} + +void nx_dpc_set_vsync(u32 module_index, u32 avheight, u32 vsw, u32 vfp, u32 vbp, + int binvvsync, u32 eavheight, u32 evsw, u32 evfp, + u32 evbp) +{ + const u32 intpend = 1u << 10; + const u32 polvsync = 1u << 1; + register u32 temp; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + writel((u32)(vsw + vbp + avheight + vfp - 1), &pregister->dpcvtotal); + + writel((u32)(vsw - 1), &pregister->dpcvswidth); + + writel((u32)(vsw + vbp - 1), &pregister->dpcvastart); + + writel((u32)(vsw + vbp + avheight - 1), &pregister->dpcvaend); + + writel((u32)(evsw + evbp + eavheight + evfp - 1), + &pregister->dpcevtotal); + + writel((u32)(evsw - 1), &pregister->dpcevswidth); + + writel((u32)(evsw + evbp - 1), &pregister->dpcevastart); + + writel((u32)(evsw + evbp + eavheight - 1), &pregister->dpcevaend); + temp = pregister->dpcctrl0; + temp &= ~intpend; + if (binvvsync) + temp |= (u32)polvsync; + else + temp &= (u32)~polvsync; + + writel(temp, &pregister->dpcctrl0); +} + +void nx_dpc_get_vsync(u32 module_index, u32 *pavheight, u32 *pvsw, u32 *pvfp, + u32 *pvbp, int *pbinvvsync, u32 *peavheight, + u32 *pevsw, u32 *pevfp, u32 *pevbp) +{ + const u32 polvsync = 1u << 1; + u32 vtotal, vsw, vab, vae; + u32 avh, vfp, vbp; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + vtotal = (u32)pregister->dpcvtotal + 1; + vsw = (u32)pregister->dpcvswidth + 1; + vab = (u32)pregister->dpcvastart + 1; + vae = (u32)pregister->dpcvaend + 1; + vbp = vab - vsw; + avh = vae - vab; + vfp = vtotal - vae; + if (pavheight) + *pavheight = avh; + if (pvsw) + *pvsw = vsw; + if (pvfp) + *pvfp = vfp; + if (pvbp) + *pvbp = vbp; + vtotal = (u32)pregister->dpcevtotal + 1; + vsw = (u32)pregister->dpcevswidth + 1; + vab = (u32)pregister->dpcevastart + 1; + vae = (u32)pregister->dpcevaend + 1; + vbp = vab - vsw; + avh = vae - vab; + vfp = vtotal - vae; + if (peavheight) + *peavheight = avh; + if (pevsw) + *pevsw = vsw; + if (pevfp) + *pevfp = vfp; + if (pevbp) + *pevbp = vbp; + if (pbinvvsync) + *pbinvvsync = (pregister->dpcctrl0 & polvsync) ? 1 : 0; +} + +void nx_dpc_set_vsync_offset(u32 module_index, u32 vssoffset, u32 vseoffset, + u32 evssoffset, u32 evseoffset) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + writel((u32)vseoffset, &pregister->dpcvseoffset); + + writel((u32)vssoffset, &pregister->dpcvssoffset); + + writel((u32)evseoffset, &pregister->dpcevseoffset); + + writel((u32)evssoffset, &pregister->dpcevssoffset); +} + +void nx_dpc_get_vsync_offset(u32 module_index, u32 *pvssoffset, + u32 *pvseoffset, u32 *pevssoffset, + u32 *pevseoffset) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + if (pvseoffset) + *pvseoffset = (u32)pregister->dpcvseoffset; + + if (pvssoffset) + *pvssoffset = (u32)pregister->dpcvssoffset; + + if (pevseoffset) + *pevseoffset = (u32)pregister->dpcevseoffset; + + if (pevssoffset) + *pevssoffset = (u32)pregister->dpcevssoffset; +} + +void nx_dpc_set_horizontal_up_scaler(u32 module_index, int benb, + u32 sourcewidth, u32 destwidth) +{ + const u32 upscalel_pos = 8; + const u32 upscaleh_pos = 0; + const u32 upscaleh_mask = ((1 << 15) - 1) << upscaleh_pos; + const u32 upscalerenb_pos = 0; + register struct nx_dpc_register_set *pregister; + register u32 regvalue; + register u32 up_scale; + + pregister = __g_module_variables[module_index].pregister; + up_scale = ((sourcewidth - 1) * (1 << 11)) / (destwidth - 1); + regvalue = 0; + regvalue |= (((u32)benb << upscalerenb_pos) | + (up_scale & 0xff) << upscalel_pos); + + writel(regvalue, &pregister->dpcupscalecon0); + + writel((up_scale >> 0x08) & upscaleh_mask, &pregister->dpcupscalecon1); + + writel(sourcewidth - 1, &pregister->dpcupscalecon2); +} + +void nx_dpc_get_horizontal_up_scaler(u32 module_index, int *pbenb, + u32 *psourcewidth, u32 *pdestwidth) +{ + const u32 upscalerenb_pos = 0; + const u32 upscalerenb_mask = 1u << upscalerenb_pos; + register struct nx_dpc_register_set *pregister; + + u32 up_scale; + u32 destwidth, srcwidth; + + pregister = __g_module_variables[module_index].pregister; + up_scale = ((u32)(pregister->dpcupscalecon1 & 0x7fff) << 8) | + ((u32)(pregister->dpcupscalecon0 >> 8) & 0xff); + srcwidth = pregister->dpcupscalecon2; + destwidth = (srcwidth * (1 << 11)) / up_scale; + if (pbenb) + *pbenb = (pregister->dpcupscalecon0 & upscalerenb_mask); + if (psourcewidth) + *psourcewidth = srcwidth + 1; + if (pdestwidth) + *pdestwidth = destwidth + 1; +} + +void nx_dpc_set_sync(u32 module_index, enum syncgenmode sync_gen_mode, + u32 avwidth, u32 avheight, u32 hsw, u32 hfp, u32 hbp, + u32 vsw, u32 vfp, u32 vbp, enum polarity field_polarity, + enum polarity hsyncpolarity, enum polarity vsyncpolarity, + u32 even_vsw, u32 even_vfp, u32 even_vbp, u32 vsetpixel, + u32 vsclrpixel, u32 evenvsetpixel, u32 evenvsclrpixel) +{ + register struct nx_dpc_register_set *pregister; + u32 regvalue = 0; + + pregister = __g_module_variables[module_index].pregister; + + writel((u32)(hfp + hsw + hbp + avwidth - 1), &pregister->dpchtotal); + writel((u32)(hsw - 1), &pregister->dpchswidth); + writel((u32)(hsw + hbp - 1), &pregister->dpchastart); + writel((u32)(hsw + hbp + avwidth - 1), &pregister->dpchaend); + writel((u32)(vfp + vsw + vbp + avheight - 1), &pregister->dpcvtotal); + writel((u32)(vsw - 1), &pregister->dpcvswidth); + writel((u32)(vsw + vbp - 1), &pregister->dpcvastart); + writel((u32)(vsw + vbp + avheight - 1), &pregister->dpcvaend); + writel((u32)vsetpixel, &pregister->dpcvseoffset); + writel((u32)(hfp + hsw + hbp + avwidth - vsclrpixel - 1), + &pregister->dpcvssoffset); + writel((u32)evenvsetpixel, &pregister->dpcevseoffset); + writel((u32)(hfp + hsw + hbp + avwidth - evenvsclrpixel - 1), + &pregister->dpcevssoffset); + if (sync_gen_mode == 1) { + writel((u32)(even_vfp + even_vsw + even_vbp + avheight - 1), + &pregister->dpcevtotal); + writel((u32)(even_vsw - 1), &pregister->dpcevswidth); + writel((u32)(even_vsw + even_vbp - 1), + &pregister->dpcevastart); + writel((u32)(even_vsw + even_vbp + avheight - 1), + &pregister->dpcevaend); + } + regvalue = readl(&pregister->dpcctrl0) & 0xfff0ul; + regvalue |= (((u32)field_polarity << 2) | ((u32)vsyncpolarity << 1) | + ((u32)hsyncpolarity << 0)); + writel((u32)regvalue, &pregister->dpcctrl0); +} + +void nx_dpc_set_output_format(u32 module_index, enum outputformat output_format, + u8 output_video_config) +{ + const u32 format_table[] = { + (0 << 0), (1 << 0), (2 << 0), (3 << 0), (4 << 0), (5 << 0), + (6 << 0), (7 << 0), (8 << 0), (9 << 0), (0 << 0) | (1 << 7), + (1 << 0) | (1 << 7), (2 << 0) | (1 << 7), (3 << 0) | (1 << 7), + (4 << 0) | (1 << 7), (5 << 0) | (1 << 7), (6 << 0) | (1 << 7), + (7 << 0) | (1 << 7), (8 << 0) | (1 << 7), (9 << 0) | (1 << 7), + (10 << 0), (11 << 0), (12 << 0), (13 << 0), (14 << 0), (15 << 0) + }; + u32 regvalue; + u32 regvalue0; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + regvalue = readl(&pregister->dpcctrl1) & 0x30fful; + + regvalue |= (format_table[output_format] << 8); + writel((u32)regvalue, &pregister->dpcctrl1); + regvalue0 = (u32)(readl(&pregister->dpcctrl1) & 0xff3f); + regvalue0 = (u32)((output_video_config << 6) | regvalue0); + writel((u32)regvalue0, &pregister->dpcctrl1); +} + +void nx_dpc_set_quantization_mode(u32 module_index, enum qmode rgb2yc, + enum qmode yc2rgb) +{ + register struct nx_dpc_register_set *pregister; + u32 regvalue; + + pregister = __g_module_variables[module_index].pregister; + regvalue = readl(&pregister->dpcctrl1) & 0x8ffful; + regvalue |= ((u32)rgb2yc << 13) | ((u32)yc2rgb << 12); + writel((u32)regvalue, &pregister->dpcctrl1); +} + +void nx_dpc_set_enable(u32 module_index, int enable, int rgbmode, + int use_ntscsync, int use_analog_output, int seavenable) +{ + u32 regvalue; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + regvalue = readl(&pregister->dpcctrl0) & 0x0efful; + regvalue |= ((u32)enable << 15) | ((u32)use_ntscsync << 14) | + ((u32)seavenable << 8) | ((u32)use_analog_output << 13) | + ((u32)rgbmode << 12); + writel((u32)regvalue, &pregister->dpcctrl0); +} + +void nx_dpc_set_out_video_clk_select(u32 module_index, + enum outpadclksel out_pad_vclk_sel) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + writel((u32)((readl(&pregister->dpcctrl2)) | (out_pad_vclk_sel & 0x3)), + &pregister->dpcctrl2); +} + +void nx_dpc_set_reg_flush(u32 module_index) +{ + u32 reg; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + reg = readl(&pregister->dpcdataflush); + writel((u32)(reg | (1ul << 4)), &pregister->dpcdataflush); +} + +void nx_dpc_set_sramon(u32 module_index) +{ + u32 reg; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + reg = (u32)(readl(&pregister->dpcctrl2) & 0xf3ff); + writel((u32)(reg | (1ul << 10)), &pregister->dpcctrl2); + reg = (u32)(readl(&pregister->dpcctrl2) & 0xf7ff); + writel((u32)(reg | (1ul << 11)), &pregister->dpcctrl2); +} + +void nx_dpc_set_sync_lcdtype(u32 module_index, int stnlcd, int dual_view_enb, + int bit_widh, u8 cpcycle) +{ + u32 reg; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + reg = (u32)(readl(&pregister->dpcctrl2) & 0xc0f); + writel((u32)(reg | (cpcycle << 12) | (bit_widh << 9) | + (dual_view_enb << 8) | (stnlcd << 7)), + &pregister->dpcctrl2); +} + +void nx_dpc_set_up_scale_control(u32 module_index, int up_scale_enb, + int filter_enb, u32 hscale, u16 source_width) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel((u32)((hscale << 8) | ((u32)filter_enb << 1) | (up_scale_enb)), + &pregister->dpcupscalecon0); + writel((u32)(hscale >> 8), &pregister->dpcupscalecon1); + writel(source_width, &pregister->dpcupscalecon2); +} + +void nx_dpc_set_mputime(u32 module_index, u8 setup, u8 hold, u8 acc) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel((u32)((setup << 8) | (hold & 0xff)), &pregister->dpcmputime0); + writel((u32)(acc), &pregister->dpcmputime1); +} + +void nx_dpc_set_index(u32 module_index, u32 index) +{ + u32 regvalue; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel((u32)(index & 0xffff), &pregister->dpcmpuwrdatal); + writel((u32)((index >> 16) & 0xff), &pregister->dpcmpuindex); + if (index == 0x22) { + regvalue = readl(&pregister->dpcctrl2); + writel((regvalue | 0x10), &pregister->dpcctrl2); + } +} + +void nx_dpc_set_data(u32 module_index, u32 data) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel((u32)(data & 0xffff), &pregister->dpcmpuwrdatal); + writel((u32)((data >> 16) & 0xff), &pregister->dpcmpudatah); +} + +void nx_dpc_set_cmd_buffer_flush(u32 module_index) +{ + u32 reg; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + reg = readl(&pregister->dpcdataflush); + writel((u32)(reg | (1 << 1)), &pregister->dpcdataflush); +} + +void nx_dpc_set_cmd_buffer_clear(u32 module_index) +{ + u32 reg; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + reg = readl(&pregister->dpcdataflush); + writel((u32)(reg | (1 << 0)), &pregister->dpcdataflush); +} + +void nx_dpc_set_cmd_buffer_write(u32 module_index, u32 cmd_data) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel((u32)(cmd_data & 0xffff), &pregister->dpccmdbufferdatal); + writel((u32)(cmd_data >> 16), &pregister->dpccmdbufferdatah); +} + +void nx_dpc_set(u32 module_index) +{ + u32 reg; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + reg = readl(&pregister->dpcpolctrl); + writel((u32)(reg | 0x1), &pregister->dpcpolctrl); +} + +u32 nx_dpc_get_data(u32 module_index) +{ + u32 reg = 0; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + reg = readl(&pregister->dpcmpudatah); + reg = (reg << 16) | readl(&pregister->dpcmpurdatal); + return reg; +} + +u32 nx_dpc_get_status(u32 module_index) +{ + u32 reg = 0; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + reg = readl(&pregister->dpcmpustatus); + reg = (reg << 16) | readl(&pregister->dpcmpurdatal); + return reg; +} + +void nx_dpc_rgbmask(u32 module_index, u32 rgbmask) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel((rgbmask >> 0) & 0xffff, &pregister->dpcrgbmask[0]); + writel((rgbmask >> 16) & 0x00ff, &pregister->dpcrgbmask[1]); +} + +void nx_dpc_set_pad_location(u32 module_index, u32 index, u32 regvalue) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel(regvalue, &pregister->dpcpadposition[index]); +} + +u32 nx_dpc_get_field_flag(u32 module_index) +{ + register struct nx_dpc_register_set *pregister; + u32 regvalue; + + pregister = __g_module_variables[module_index].pregister; + regvalue = readl(&pregister->dpcrgbshift); + + return (u32)((regvalue >> 5) & 0x01); +} + +void nx_dpc_set_enable_with_interlace(u32 module_index, int enable, int rgbmode, + int use_ntscsync, int use_analog_output, + int seavenable) +{ + u32 regvalue; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + regvalue = readl(&pregister->dpcctrl0) & 0x0eff; + regvalue = readl(&pregister->dpcctrl0) & 0x0eff; + regvalue |= ((u32)enable << 15) | ((u32)use_ntscsync << 14) | + ((u32)seavenable << 8) | ((u32)use_analog_output << 13) | + ((u32)rgbmode << 12); + + regvalue |= (1 << 9); + writel((u16)regvalue, &pregister->dpcctrl0); +} + +void nx_dpc_set_encoder_control_reg(u32 module_index, u32 param_a, u32 param_b, + u32 param_c) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel(param_a, &pregister->ntsc_ecmda); + writel(param_b, &pregister->ntsc_ecmdb); + writel(param_c, &pregister->ntsc_ecmdc); +} + +void nx_dpc_set_encoder_shcphase_control(u32 module_index, u32 chroma_param) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel(chroma_param, &pregister->ntsc_sch); +} + +void nx_dpc_set_encoder_timing_config_reg(u32 module_index, u32 icntl) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel(icntl, &pregister->ntsc_icntl); +} + +void nx_dpc_set_encoder_dacoutput_select(u32 module_index, u8 dacsel0, + u8 dacsel1, u8 dacsel2, u8 dacsel3, + u8 dacsel4, u8 dacsel5) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel(((dacsel1 & 0xf) << 4) | (dacsel0 & 0xf), + &pregister->ntsc_dacsel10); + writel(((dacsel3 & 0xf) << 4) | (dacsel2 & 0xf), + &pregister->ntsc_dacsel32); + writel(((dacsel5 & 0xf) << 4) | (dacsel4 & 0xf), + &pregister->ntsc_dacsel54); +} + +void nx_dpc_set_encoder_sync_location(u32 module_index, u16 hsoe, u16 hsob, + u16 vsob, u16 vsoe, u8 vsost, int novrst) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel((u16)((((vsob & 0x100) >> 2) | ((hsob & 0x700) >> 5) | + (hsoe & 0x700) >> 8)), &pregister->ntsc_hsvso); + writel((u16)(hsoe & 0xff), &pregister->ntsc_hsoe); + writel((u16)(hsob & 0xff), &pregister->ntsc_hsob); + writel((u16)(vsob & 0xff), &pregister->ntsc_vsob); + writel((u16)(((vsost & 0x3) << 6) | (novrst << 5) | (vsoe & 0x1f)), + &pregister->ntsc_vsoe); +} + +void nx_dpc_set_encoder_dacpower_enable(u32 module_index, u8 dacpd) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel(dacpd, &pregister->ntsc_dacpd); +} + +void nx_dpc_set_ycorder(u32 module_index, enum nx_dpc_ycorder ycorder) +{ + const u16 ycorder_pos = 6; + register struct nx_dpc_register_set *pregister; + u32 temp; + + pregister = __g_module_variables[module_index].pregister; + temp = pregister->dpcctrl1 & (~(0xf << ycorder_pos)); + temp = (u16)(temp | (ycorder << ycorder_pos)); + writel(temp, &pregister->dpcctrl1); +} + +void nx_dpc_set_luma_gain(u32 module_index, u32 luma_gain) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel(luma_gain, &pregister->ntsc_cont); +} + +void nx_dpc_set_encenable(u32 module_index, int benb) +{ + const u16 encmode = 1u << 14; + const u16 encrst = 1u << 13; + const u16 intpend = 1u << 10; + register struct nx_dpc_register_set *pregister; + register u16 temp; + + pregister = __g_module_variables[module_index].pregister; + temp = readl(&pregister->dpcctrl0); + temp &= (u16)~intpend; + if (benb) + temp |= (u16)encrst; + else + temp &= (u16)~encrst; + writel((temp | encmode), &pregister->dpcctrl0); + writel(7, &pregister->ntsc_icntl); +} + +int nx_dpc_get_encenable(u32 module_index) +{ + const u16 encrst = 1u << 13; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + return (readl(&pregister->dpcctrl0) & encrst) ? 1 : 0; +} + +void nx_dpc_set_video_encoder_power_down(u32 module_index, int benb) +{ + const u16 pwdenc = 1u << 7; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + if (benb) { + writel(readl(&pregister->ntsc_ecmda) | (u16)pwdenc, + &pregister->ntsc_ecmda); + writel(0, &pregister->ntsc_dacsel10); + } else { + writel(1, &pregister->ntsc_dacsel10); + writel(readl(&pregister->ntsc_ecmda) & (u16)~pwdenc, + &pregister->ntsc_ecmda); + } +} + +int nx_dpc_get_video_encoder_power_down(u32 module_index) +{ + const u16 pwdenc = 1u << 7; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + return (readl(&pregister->ntsc_ecmda) & pwdenc) ? 1 : 0; +} + +void nx_dpc_set_video_encoder_mode(u32 module_index, enum nx_dpc_vbs vbs, + int bpedestal) +{ + register struct nx_dpc_register_set *pregister; + +#define phalt (1u << 0) +#define ifmt (1u << 1) +#define ped (1u << 3) +#define fscsel_ntsc (0u << 4) +#define fscsel_pal (1u << 4) +#define fscsel_palm (2u << 4) +#define fscsel_paln (3u << 4) +#define fdrst (1u << 6) +#define pwdenc (1u << 7) + register u16 temp; + static const u8 ntsc_ecmda_table[] = { + (u8)(fscsel_ntsc | fdrst), (u8)(ifmt | fscsel_ntsc), + (u8)(fscsel_pal), (u8)(fscsel_palm | phalt), + (u8)(ifmt | fscsel_paln | phalt), + (u8)(ifmt | fscsel_pal | phalt | fdrst), + (u8)(fscsel_pal | phalt), + (u8)(ifmt | fscsel_ntsc) + }; + pregister = __g_module_variables[module_index].pregister; + temp = readl(&pregister->ntsc_ecmda); + temp &= (u16)pwdenc; + temp = (u16)(temp | (u16)ntsc_ecmda_table[vbs]); + if (bpedestal) + temp |= (u16)ped; + writel(temp, &pregister->ntsc_ecmda); +#undef phalt +#undef ifmt +#undef ped +#undef fscsel_ntsc +#undef fscsel_pal +#undef fscsel_palm +#undef fscsel_paln +#undef fdrst +#undef pwdenc +} + +void nx_dpc_set_video_encoder_schlock_control(u32 module_index, int bfreerun) +{ + const u16 fdrst = 1u << 6; + register struct nx_dpc_register_set *pregister; + register u16 temp; + + pregister = __g_module_variables[module_index].pregister; + temp = readl(&pregister->ntsc_ecmda); + if (bfreerun) + temp |= (u16)fdrst; + else + temp &= (u16)~fdrst; + writel(temp, &pregister->ntsc_ecmda); +} + +int nx_dpc_get_video_encoder_schlock_control(u32 module_index) +{ + const u16 fdrst = 1u << 6; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + return (readl(&pregister->ntsc_ecmda) & fdrst) ? 1 : 0; +} + +void nx_dpc_set_video_encoder_bandwidth(u32 module_index, + enum nx_dpc_bandwidth luma, + enum nx_dpc_bandwidth chroma) +{ + const u16 ybw_pos = 0; + const u16 cbw_pos = 2; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel((u16)((chroma << cbw_pos) | (luma << ybw_pos)), + &pregister->ntsc_ecmdb); +} + +void nx_dpc_get_video_encoder_bandwidth(u32 module_index, + enum nx_dpc_bandwidth *pluma, + enum nx_dpc_bandwidth *pchroma) +{ + const u16 ybw_pos = 0; + const u16 ybw_mask = 3u << ybw_pos; + const u16 cbw_pos = 2; + const u16 cbw_mask = 3u << cbw_pos; + register struct nx_dpc_register_set *pregister; + register u16 temp; + + pregister = __g_module_variables[module_index].pregister; + temp = readl(&pregister->ntsc_ecmdb); + if (pluma) + *pluma = (enum nx_dpc_bandwidth)((temp & ybw_mask) >> ybw_pos); + if (pchroma) + *pchroma = + (enum nx_dpc_bandwidth)((temp & cbw_mask) >> cbw_pos); +} + +void nx_dpc_set_video_encoder_color_control(u32 module_index, s8 sch, + s8 hue, s8 sat, s8 crt, + s8 brt) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel((u16)sch, &pregister->ntsc_sch); + writel((u16)hue, &pregister->ntsc_hue); + writel((u16)sat, &pregister->ntsc_sat); + writel((u16)crt, &pregister->ntsc_cont); + writel((u16)brt, &pregister->ntsc_bright); +} + +void nx_dpc_get_video_encoder_color_control(u32 module_index, s8 *psch, + s8 *phue, s8 *psat, + s8 *pcrt, s8 *pbrt) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + if (psch) + *psch = (s8)readl(&pregister->ntsc_sch); + if (phue) + *phue = (s8)readl(&pregister->ntsc_hue); + if (psat) + *psat = (s8)readl(&pregister->ntsc_sat); + if (pcrt) + *pcrt = (s8)readl(&pregister->ntsc_cont); + if (pbrt) + *pbrt = (s8)readl(&pregister->ntsc_bright); +} + +void nx_dpc_set_video_encoder_fscadjust(u32 module_index, int16_t adjust) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel((u16)(adjust >> 8), &pregister->ntsc_fsc_adjh); + writel((u16)(adjust & 0xff), &pregister->ntsc_fsc_adjl); +} + +u16 nx_dpc_get_video_encoder_fscadjust(u32 module_index) +{ + register u32 temp; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + temp = (u32)readl(&pregister->ntsc_fsc_adjh); + temp <<= 8; + temp |= (((u32)readl(&pregister->ntsc_fsc_adjl)) & 0xff); + return (u16)temp; +} + +void nx_dpc_set_video_encoder_timing(u32 module_index, u32 hsos, u32 hsoe, + u32 vsos, u32 vsoe) +{ + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + hsos -= 1; + hsoe -= 1; + writel((u16)((((vsos >> 8) & 1u) << 6) | (((hsos >> 8) & 7u) << 3) | + (((hsoe >> 8) & 7u) << 0)), &pregister->ntsc_hsvso); + writel((u16)(hsos & 0xffu), &pregister->ntsc_hsob); + writel((u16)(hsoe & 0xffu), &pregister->ntsc_hsoe); + writel((u16)(vsos & 0xffu), &pregister->ntsc_vsob); + writel((u16)(vsoe & 0x1fu), &pregister->ntsc_vsoe); +} + +void nx_dpc_get_video_encoder_timing(u32 module_index, u32 *phsos, u32 *phsoe, + u32 *pvsos, u32 *pvsoe) +{ + register u16 hsvso; + register struct nx_dpc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + hsvso = readl(&pregister->ntsc_hsvso); + if (phsos) + *phsos = (u32)((((hsvso >> 3) & 7u) << 8) | + (readl(&pregister->ntsc_hsob) & 0xffu)) + 1; + if (phsoe) + *phsoe = (u32)((((hsvso >> 0) & 7u) << 8) | + (readl(&pregister->ntsc_hsoe) & 0xffu)) + 1; + if (pvsos) + *pvsos = (u32)((((hsvso >> 6) & 1u) << 8) | + (readl(&pregister->ntsc_vsob) & 0xffu)); + if (pvsoe) + *pvsoe = (u32)(readl(&pregister->ntsc_vsoe) & 0x1fu); +} diff --git a/drivers/video/nexell/soc/s5pxx18_soc_dpc.h b/drivers/video/nexell/soc/s5pxx18_soc_dpc.h new file mode 100644 index 0000000000..cfa53c3fdb --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_dpc.h @@ -0,0 +1,444 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#ifndef _S5PXX18_SOC_DPC_H_ +#define _S5PXX18_SOC_DPC_H_ + +#include "s5pxx18_soc_disptype.h" + +#define IRQ_OFFSET 32 +#define IRQ_DPC_P (IRQ_OFFSET + 33) +#define IRQ_DPC_S (IRQ_OFFSET + 34) + +#define NUMBER_OF_DPC_MODULE 2 +#define PHY_BASEADDR_DPC0 0xC0102800 +#define PHY_BASEADDR_DPC1 0xC0102C00 + +#define PHY_BASEADDR_DPC_LIST \ + { PHY_BASEADDR_DPC0, PHY_BASEADDR_DPC1 } + +struct nx_dpc_register_set { + u32 ntsc_stata; + u32 ntsc_ecmda; + u32 ntsc_ecmdb; + u32 ntsc_glk; + u32 ntsc_sch; + u32 ntsc_hue; + u32 ntsc_sat; + u32 ntsc_cont; + u32 ntsc_bright; + u32 ntsc_fsc_adjh; + u32 ntsc_fsc_adjl; + u32 ntsc_ecmdc; + u32 ntsc_csdly; + u32 __ntsc_reserved_0_[3]; + u32 ntsc_dacsel10; + u32 ntsc_dacsel32; + u32 ntsc_dacsel54; + u32 ntsc_daclp; + u32 ntsc_dacpd; + u32 __ntsc_reserved_1_[(0x20 - 0x15)]; + u32 ntsc_icntl; + u32 ntsc_hvoffst; + u32 ntsc_hoffst; + u32 ntsc_voffset; + u32 ntsc_hsvso; + u32 ntsc_hsob; + u32 ntsc_hsoe; + u32 ntsc_vsob; + u32 ntsc_vsoe; + u32 __reserved[(0xf8 / 4) - 0x29]; + u32 dpchtotal; + u32 dpchswidth; + u32 dpchastart; + u32 dpchaend; + u32 dpcvtotal; + u32 dpcvswidth; + u32 dpcvastart; + u32 dpcvaend; + u32 dpcctrl0; + u32 dpcctrl1; + u32 dpcevtotal; + u32 dpcevswidth; + u32 dpcevastart; + u32 dpcevaend; + u32 dpcctrl2; + u32 dpcvseoffset; + u32 dpcvssoffset; + u32 dpcevseoffset; + u32 dpcevssoffset; + u32 dpcdelay0; + u32 dpcupscalecon0; + u32 dpcupscalecon1; + u32 dpcupscalecon2; + + u32 dpcrnumgencon0; + u32 dpcrnumgencon1; + u32 dpcrnumgencon2; + u32 dpcrndconformula_l; + u32 dpcrndconformula_h; + u32 dpcfdtaddr; + u32 dpcfrdithervalue; + u32 dpcfgdithervalue; + u32 dpcfbdithervalue; + u32 dpcdelay1; + u32 dpcmputime0; + u32 dpcmputime1; + u32 dpcmpuwrdatal; + u32 dpcmpuindex; + u32 dpcmpustatus; + u32 dpcmpudatah; + u32 dpcmpurdatal; + u32 dpcdummy12; + u32 dpccmdbufferdatal; + u32 dpccmdbufferdatah; + u32 dpcpolctrl; + u32 dpcpadposition[8]; + u32 dpcrgbmask[2]; + u32 dpcrgbshift; + u32 dpcdataflush; + u32 __reserved06[((0x3c0) - (2 * 0x0ec)) / 4]; + + u32 dpcclkenb; + u32 dpcclkgen[2][2]; +}; + +enum { + nx_dpc_int_vsync = 0 +}; + +enum nx_dpc_format { + nx_dpc_format_rgb555 = 0ul, + nx_dpc_format_rgb565 = 1ul, + nx_dpc_format_rgb666 = 2ul, + nx_dpc_format_rgb666b = 18ul, + nx_dpc_format_rgb888 = 3ul, + nx_dpc_format_mrgb555a = 4ul, + nx_dpc_format_mrgb555b = 5ul, + nx_dpc_format_mrgb565 = 6ul, + nx_dpc_format_mrgb666 = 7ul, + nx_dpc_format_mrgb888a = 8ul, + nx_dpc_format_mrgb888b = 9ul, + nx_dpc_format_ccir656 = 10ul, + nx_dpc_format_ccir601a = 12ul, + nx_dpc_format_ccir601b = 13ul, + nx_dpc_format_srgb888 = 14ul, + nx_dpc_format_srgbd8888 = 15ul, + nx_dpc_format_4096color = 1ul, + nx_dpc_format_16gray = 3ul +}; + +enum nx_dpc_ycorder { + nx_dpc_ycorder_cb_ycr_y = 0ul, + nx_dpc_ycorder_cr_ycb_y = 1ul, + nx_dpc_ycorder_ycbycr = 2ul, + nx_dpc_ycorder_ycrycb = 3ul +}; + +enum nx_dpc_padclk { + nx_dpc_padclk_vclk = 0ul, + nx_dpc_padclk_vclk2 = 1ul, + nx_dpc_padclk_vclk3 = 2ul +}; + +enum nx_dpc_dither { + nx_dpc_dither_bypass = 0ul, + nx_dpc_dither_4bit = 1ul, + nx_dpc_dither_5bit = 2ul, + nx_dpc_dither_6bit = 3ul +}; + +enum nx_dpc_vbs { + nx_dpc_vbs_ntsc_m = 0ul, + nx_dpc_vbs_ntsc_n = 1ul, + nx_dpc_vbs_ntsc_443 = 2ul, + nx_dpc_vbs_pal_m = 3ul, + nx_dpc_vbs_pal_n = 4ul, + nx_dpc_vbs_pal_bghi = 5ul, + nx_dpc_vbs_pseudo_pal = 6ul, + nx_dpc_vbs_pseudo_ntsc = 7ul +}; + +enum nx_dpc_bandwidth { + nx_dpc_bandwidth_low = 0ul, + nx_dpc_bandwidth_medium = 1ul, + nx_dpc_bandwidth_high = 2ul +}; + +int nx_dpc_initialize(void); +u32 nx_dpc_get_number_of_module(void); +u32 nx_dpc_get_physical_address(u32 module_index); +u32 nx_dpc_get_size_of_register_set(void); +void nx_dpc_set_base_address(u32 module_index, void *base_address); +void *nx_dpc_get_base_address(u32 module_index); +int nx_dpc_open_module(u32 module_index); +int nx_dpc_close_module(u32 module_index); +int nx_dpc_check_busy(u32 module_index); +int nx_dpc_can_power_down(u32 module_index); +int32_t nx_dpc_get_interrupt_number(u32 module_index); +void nx_dpc_set_interrupt_enable(u32 module_index, int32_t int_num, + int enable); +int nx_dpc_get_interrupt_enable(u32 module_index, int32_t int_num); +int nx_dpc_get_interrupt_pending(u32 module_index, int32_t int_num); +void nx_dpc_clear_interrupt_pending(u32 module_index, int32_t int_num); +void nx_dpc_set_interrupt_enable_all(u32 module_index, int enable); +int nx_dpc_get_interrupt_enable_all(u32 module_index); +int nx_dpc_get_interrupt_pending_all(u32 module_index); +void nx_dpc_clear_interrupt_pending_all(u32 module_index); +void nx_dpc_set_interrupt_enable32(u32 module_index, u32 enable_flag); +u32 nx_dpc_get_interrupt_enable32(u32 module_index); +u32 nx_dpc_get_interrupt_pending32(u32 module_index); +void nx_dpc_clear_interrupt_pending32(u32 module_index, + u32 pending_flag); +int32_t nx_dpc_get_interrupt_pending_number(u32 module_index); +void nx_dpc_set_clock_pclk_mode(u32 module_index, enum nx_pclkmode mode); +enum nx_pclkmode nx_dpc_get_clock_pclk_mode(u32 module_index); +void nx_dpc_set_clock_source(u32 module_index, u32 index, u32 clk_src); +u32 nx_dpc_get_clock_source(u32 module_index, u32 index); +void nx_dpc_set_clock_divisor(u32 module_index, u32 index, u32 divisor); +u32 nx_dpc_get_clock_divisor(u32 module_index, u32 index); +void nx_dpc_set_clock_out_inv(u32 module_index, u32 index, + int out_clk_inv); +int nx_dpc_get_clock_out_inv(u32 module_index, u32 index); +void nx_dpc_set_clock_out_select(u32 module_index, u32 index, + int bbypass); +int nx_dpc_get_clock_out_select(u32 module_index, u32 index); +void nx_dpc_set_clock_polarity(u32 module_index, int bpolarity); +int nx_dpc_get_clock_polarity(u32 module_index); +void nx_dpc_set_clock_out_enb(u32 module_index, u32 index, + int out_clk_enb); +int nx_dpc_get_clock_out_enb(u32 module_index, u32 index); +void nx_dpc_set_clock_out_delay(u32 module_index, u32 index, u32 delay); +u32 nx_dpc_get_clock_out_delay(u32 module_index, u32 index); +void nx_dpc_set_clock_divisor_enable(u32 module_index, int enable); +int nx_dpc_get_clock_divisor_enable(u32 module_index); + +void nx_dpc_set_dpc_enable(u32 module_index, int benb); +int nx_dpc_get_dpc_enable(u32 module_index); +void nx_dpc_set_delay(u32 module_index, u32 delay_rgb_pvd, + u32 delay_hs_cp1, u32 delay_vs_fram, + u32 delay_de_cp2); +void nx_dpc_get_delay(u32 module_index, u32 *pdelayrgb_pvd, + u32 *pdelayhs_cp1, u32 *pdelayvs_fram, + u32 *pdelayde_cp2); +void nx_dpc_set_dither(u32 module_index, enum nx_dpc_dither dither_r, + enum nx_dpc_dither dither_g, + enum nx_dpc_dither dither_b); +void nx_dpc_get_dither(u32 module_index, enum nx_dpc_dither *pditherr, + enum nx_dpc_dither *pditherg, + enum nx_dpc_dither *pditherb); +void nx_dpc_set_horizontal_up_scaler(u32 module_index, int benb, + u32 sourcewidth, u32 destwidth); +void nx_dpc_get_horizontal_up_scaler(u32 module_index, int *pbenb, + u32 *psourcewidth, + u32 *pdestwidth); + +void nx_dpc_set_mode(u32 module_index, enum nx_dpc_format format, + int binterlace, int binvertfield, int brgbmode, + int bswaprb, enum nx_dpc_ycorder ycorder, + int bclipyc, int bembeddedsync, + enum nx_dpc_padclk clock, int binvertclock, + int bdualview); +void nx_dpc_get_mode(u32 module_index, enum nx_dpc_format *pformat, + int *pbinterlace, int *pbinvertfield, + int *pbrgbmode, int *pbswaprb, + enum nx_dpc_ycorder *pycorder, int *pbclipyc, + int *pbembeddedsync, enum nx_dpc_padclk *pclock, + int *pbinvertclock, int *pbdualview); +void nx_dpc_set_hsync(u32 module_index, u32 avwidth, u32 hsw, u32 hfp, + u32 hbp, int binvhsync); +void nx_dpc_get_hsync(u32 module_index, u32 *pavwidth, u32 *phsw, + u32 *phfp, u32 *phbp, int *pbinvhsync); +void nx_dpc_set_vsync(u32 module_index, u32 avheight, u32 vsw, u32 vfp, + u32 vbp, int binvvsync, u32 eavheight, u32 evsw, + u32 evfp, u32 evbp); +void nx_dpc_get_vsync(u32 module_index, u32 *pavheight, u32 *pvsw, + u32 *pvfp, u32 *pvbp, int *pbinvvsync, + u32 *peavheight, u32 *pevsw, u32 *pevfp, + u32 *pevbp); +void nx_dpc_set_vsync_offset(u32 module_index, u32 vssoffset, + u32 vseoffset, u32 evssoffset, + u32 evseoffset); +void nx_dpc_get_vsync_offset(u32 module_index, u32 *pvssoffset, + u32 *pvseoffset, u32 *pevssoffset, + u32 *pevseoffset); + +u32 nx_dpc_enable_pad_tft(u32 module_index, u32 mode_index); +u32 nx_dpc_enable_pad_i80(u32 module_index, u32 mode_index); + +enum syncgenmode { + progressive = 0, + interlace = 1 +}; + +enum polarity { + polarity_activehigh = 0, + polarity_activelow = 1 +}; + +enum outputformat { + outputformat_rgb555 = 0, + outputformat_rgb565 = 1, + outputformat_rgb666 = 2, + outputformat_rgb888 = 3, + outputformat_mrgb555a = 4, + outputformat_mrgb555b = 5, + outputformat_mrgb565 = 6, + outputformat_mrgb666 = 7, + outputformat_mrgb888a = 8, + outputformat_mrgb888b = 9, + outputformat_bgr555 = 10, + outputformat_bgr565 = 11, + outputformat_bgr666 = 12, + outputformat_bgr888 = 13, + outputformat_mbgr555a = 14, + outputformat_mbgr555b = 15, + outputformat_mbgr565 = 16, + outputformat_mbgr666 = 17, + outputformat_mbgr888a = 18, + outputformat_mbgr888b = 19, + outputformat_ccir656 = 20, + outputformat_ccir601_8 = 21, + outputformat_ccir601_16a = 22, + outputformat_ccir601_16b = 23, + outputformat_srgb888 = 24, + outputformat_srgbd8888 = 25 +}; + +enum outpadclksel { + padvclk = 0, + padvclk2 = 1, + padvclk3 = 2 +}; + +enum qmode { + qmode_220 = 0, + qmode_256 = 1 +}; + +void nx_dpc_set_sync(u32 module_index, enum syncgenmode sync_gen_mode, + u32 avwidth, u32 avheight, u32 hsw, u32 hfp, + u32 hbp, u32 vsw, u32 vfp, u32 vbp, + enum polarity field_polarity, + enum polarity hsyncpolarity, + enum polarity vsyncpolarity, u32 even_vsw, + u32 even_vfp, u32 even_vbp, u32 vsetpixel, + u32 vsclrpixel, u32 evenvsetpixel, + u32 evenvsclrpixel); +void nx_dpc_set_output_format(u32 module_index, + enum outputformat output_format, + u8 output_video_config); +void nx_dpc_set_quantization_mode(u32 module_index, enum qmode rgb2yc, + enum qmode yc2rgb); +void nx_dpc_set_enable(u32 module_index, int enable, int rgbmode, + int use_ntscsync, int use_analog_output, + int seavenable); +void nx_dpc_set_enable_with_interlace(u32 module_index, int enable, + int rgbmode, int use_ntscsync, + int use_analog_output, + int seavenable); +void nx_dpc_set_enable_with_interlace(u32 module_index, int enable, + int rgbmode, int use_ntscsync, + int use_analog_output, + int seavenable); +void nx_dpc_set_out_video_clk_select(u32 module_index, + enum outpadclksel out_pad_vclk_sel); +void nx_dpc_set_reg_flush(u32 module_index); +void nx_dpc_set_sramon(u32 module_index); +void nx_dpc_set_sync_lcdtype(u32 module_index, int stnlcd, + int dual_view_enb, int bit_widh, + u8 cpcycle); +void nx_dpc_set_up_scale_control(u32 module_index, int up_scale_enb, + int filter_enb, u32 hscale, + u16 source_width); + +void nx_dpc_set_mputime(u32 module_index, u8 setup, u8 hold, u8 acc); +void nx_dpc_set_index(u32 module_index, u32 index); +void nx_dpc_set_data(u32 module_index, u32 data); +void nx_dpc_set_cmd_buffer_flush(u32 module_index); +void nx_dpc_set_cmd_buffer_clear(u32 module_index); +void nx_dpc_set_cmd_buffer_write(u32 module_index, u32 cmd_data); +void nx_dpc_set(u32 module_index); +u32 nx_dpc_get_data(u32 module_index); +u32 nx_dpc_get_status(u32 module_index); +void nx_dpc_rgbmask(u32 module_index, u32 rgbmask); +void nx_dpc_set_pad_location(u32 module_index, u32 index, u32 regvalue); +u32 nx_dpc_get_field_flag(u32 module_index); + +void nx_dpc_set_sync_v(u32 module_index, u32 avheight, u32 vsw, u32 vfp, + u32 vbp); + +int nx_dpc_init_reg_test(u32 module_index); +void nx_dpc_set_encoder_control_reg(u32 module_index, u32 param_a, + u32 param_b, u32 param_c); +void nx_dpc_set_encoder_shcphase_control(u32 module_index, + u32 chroma_param); +void nx_dpc_set_encoder_timing_config_reg(u32 module_index, u32 inctl); +void nx_dpc_set_encoder_dacoutput_select(u32 module_index, u8 dacsel0, + u8 dacsel1, u8 dacsel2, + u8 dacsel3, u8 dacsel4, + u8 dacsel5); +void nx_dpc_set_encoder_sync_location(u32 module_index, u16 hsoe, + u16 hsob, u16 vsob, u16 vsoe, + u8 vsost, int novrst); +void nx_dpc_set_encoder_dacpower_enable(u32 module_index, u8 dacpd); +void nx_dpc_set_ycorder(u32 module_index, enum nx_dpc_ycorder ycorder); +void nx_dpc_set_luma_gain(u32 module_index, u32 luma_gain); + +void nx_dpc_set_secondary_dpcsync(u32 module_index, int benb); +int nx_dpc_get_secondary_dpcsync(u32 module_index); +void nx_dpc_set_encenable(u32 module_index, int benb); +int nx_dpc_get_encenable(u32 module_index); +void nx_dpc_set_video_encoder_power_down(u32 module_index, int benb); +int nx_dpc_get_video_encoder_power_down(u32 module_index); +void nx_dpc_set_video_encoder_mode(u32 module_index, enum nx_dpc_vbs vbs, + int bpedestal); +void nx_dpc_set_video_encoder_schlock_control(u32 module_index, + int bfreerun); +int nx_dpc_get_video_encoder_schlock_control(u32 module_index); +void nx_dpc_set_video_encoder_bandwidth(u32 module_index, + enum nx_dpc_bandwidth luma, + enum nx_dpc_bandwidth chroma); +void nx_dpc_get_video_encoder_bandwidth(u32 module_index, + enum nx_dpc_bandwidth *pluma, + enum nx_dpc_bandwidth *pchroma); +void nx_dpc_set_video_encoder_color_control(u32 module_index, s8 sch, + s8 hue, s8 sat, + s8 crt, s8 brt); +void nx_dpc_get_video_encoder_color_control(u32 module_index, + s8 *psch, s8 *phue, + s8 *psat, s8 *pcrt, + s8 *pbrt); +void nx_dpc_set_video_encoder_fscadjust(u32 module_index, + int16_t adjust); +u16 nx_dpc_get_video_encoder_fscadjust(u32 module_index); +void nx_dpc_set_video_encoder_timing(u32 module_index, u32 hsos, + u32 hsoe, u32 vsos, u32 vsoe); +void nx_dpc_get_video_encoder_timing(u32 module_index, u32 *phsos, + u32 *phsoe, u32 *pvsos, + u32 *pvsoe); +void nx_dpc_set_sync_v(u32 module_index, u32 avheight, u32 vsw, u32 vfp, + u32 vbp); + +int nx_dpc_init_reg_test(u32 module_index); +void nx_dpc_set_encoder_control_reg(u32 module_index, u32 param_a, + u32 param_b, u32 param_c); +void nx_dpc_set_encoder_shcphase_control(u32 module_index, + u32 chroma_param); +void nx_dpc_set_encoder_timing_config_reg(u32 module_index, u32 inctl); +void nx_dpc_set_encoder_dacoutput_select(u32 module_index, u8 dacsel0, + u8 dacsel1, u8 dacsel2, + u8 dacsel3, u8 dacsel4, + u8 dacsel5); +void nx_dpc_set_encoder_sync_location(u32 module_index, u16 hsoe, + u16 hsob, u16 vsob, u16 vsoe, + u8 vsost, int novrst); +void nx_dpc_set_encoder_dacpower_enable(u32 module_index, u8 dacpd); +void nx_dpc_set_ycorder(u32 module_index, enum nx_dpc_ycorder ycorder); +void nx_dpc_set_luma_gain(u32 module_index, u32 luma_gain); + +#endif diff --git a/drivers/video/nexell/soc/s5pxx18_soc_hdmi.c b/drivers/video/nexell/soc/s5pxx18_soc_hdmi.c new file mode 100644 index 0000000000..7b8be7e2b5 --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_hdmi.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#include <linux/types.h> +#include <linux/io.h> + +#include "s5pxx18_soc_hdmi.h" + +static u32 *hdmi_base_addr; + +u32 nx_hdmi_get_reg(u32 module_index, u32 offset) +{ + u32 *reg_addr; + u32 regvalue; + + reg_addr = hdmi_base_addr + (offset / sizeof(u32)); + regvalue = readl((u32 *)reg_addr); + + return regvalue; +} + +void nx_hdmi_set_reg(u32 module_index, u32 offset, u32 regvalue) +{ + s64 offset_new = (s64)((int32_t)offset); + u32 *reg_addr; + + reg_addr = hdmi_base_addr + (offset_new / sizeof(u32)); + writel(regvalue, (u32 *)reg_addr); +} + +void nx_hdmi_set_base_address(u32 module_index, void *base_address) +{ + hdmi_base_addr = (u32 *)base_address; +} + +void *nx_hdmi_get_base_address(u32 module_index) +{ + return (u32 *)hdmi_base_addr; +} + +u32 nx_hdmi_get_physical_address(u32 module_index) +{ + const u32 physical_addr[] = PHY_BASEADDR_HDMI_LIST; + + return physical_addr[module_index]; +} diff --git a/drivers/video/nexell/soc/s5pxx18_soc_hdmi.h b/drivers/video/nexell/soc/s5pxx18_soc_hdmi.h new file mode 100644 index 0000000000..a4c5ab5e59 --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_hdmi.h @@ -0,0 +1,488 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#ifndef _S5PXX18_SOC_HDMI_H_ +#define _S5PXX18_SOC_HDMI_H_ + +#include "s5pxx18_soc_disptop.h" + +#define PHY_BASEADDR_HDMI_PHY_MODULE 0xc00f0000 +#define PHY_BASEADDR_HDMI_LIST \ + { PHY_BASEADDR_HDMI_MODULE } + +#define HDMI_LINK_INTC_CON_0 (HDMI_ADDR_OFFSET + 0x00000000) +#define HDMI_LINK_INTC_FLAG_0 (HDMI_ADDR_OFFSET + 0x00000004) +#define HDMI_LINK_AESKEY_VALID (HDMI_ADDR_OFFSET + 0x00000008) +#define HDMI_LINK_HPD (HDMI_ADDR_OFFSET + 0x0000000C) +#define HDMI_LINK_INTC_CON_1 (HDMI_ADDR_OFFSET + 0x00000010) +#define HDMI_LINK_INTC_FLAG_1 (HDMI_ADDR_OFFSET + 0x00000014) +#define HDMI_LINK_PHY_STATUS_0 (HDMI_ADDR_OFFSET + 0x00000020) +#define HDMI_LINK_PHY_STATUS_CMU (HDMI_ADDR_OFFSET + 0x00000024) +#define HDMI_LINK_PHY_STATUS_PLL (HDMI_ADDR_OFFSET + 0x00000028) +#define HDMI_LINK_PHY_CON_0 (HDMI_ADDR_OFFSET + 0x00000030) +#define HDMI_LINK_HPD_CTRL (HDMI_ADDR_OFFSET + 0x00000040) +#define HDMI_LINK_HPD_STATUS (HDMI_ADDR_OFFSET + 0x00000044) +#define HDMI_LINK_HPD_TH_x (HDMI_ADDR_OFFSET + 0x00000050) + +#define HDMI_LINK_HDMI_CON_0 (HDMI_ADDR_OFFSET + 0x00010000) +#define HDMI_LINK_HDMI_CON_1 (HDMI_ADDR_OFFSET + 0x00010004) +#define HDMI_LINK_HDMI_CON_2 (HDMI_ADDR_OFFSET + 0x00010008) +#define HDMI_LINK_STATUS (HDMI_ADDR_OFFSET + 0x00010010) +#define HDMI_LINK_STATUS_EN (HDMI_ADDR_OFFSET + 0x00010020) + +#define HDMI_LINK_HDCP_SHA1_REN0 (HDMI_ADDR_OFFSET + 0x00010024) +#define HDMI_LINK_HDCP_SHA1_REN1 (HDMI_ADDR_OFFSET + 0x00010028) + +#define HDMI_LINK_MODE_SEL (HDMI_ADDR_OFFSET + 0x00010040) +#define HDMI_LINK_ENC_EN (HDMI_ADDR_OFFSET + 0x00010044) +#define HDMI_LINK_HDMI_YMAX (HDMI_ADDR_OFFSET + 0x00010060) +#define HDMI_LINK_HDMI_YMIN (HDMI_ADDR_OFFSET + 0x00010064) +#define HDMI_LINK_HDMI_CMAX (HDMI_ADDR_OFFSET + 0x00010068) +#define HDMI_LINK_HDMI_CMIN (HDMI_ADDR_OFFSET + 0x0001006C) +#define HDMI_LINK_H_BLANK_0 (HDMI_ADDR_OFFSET + 0x000100A0) +#define HDMI_LINK_H_BLANK_1 (HDMI_ADDR_OFFSET + 0x000100A4) +#define HDMI_LINK_V2_BLANK_0 (HDMI_ADDR_OFFSET + 0x000100B0) +#define HDMI_LINK_V2_BLANK_1 (HDMI_ADDR_OFFSET + 0x000100B4) +#define HDMI_LINK_V1_BLANK_0 (HDMI_ADDR_OFFSET + 0x000100B8) +#define HDMI_LINK_V1_BLANK_1 (HDMI_ADDR_OFFSET + 0x000100BC) +#define HDMI_LINK_V_LINE_0 (HDMI_ADDR_OFFSET + 0x000100C0) +#define HDMI_LINK_V_LINE_1 (HDMI_ADDR_OFFSET + 0x000100C4) +#define HDMI_LINK_H_LINE_0 (HDMI_ADDR_OFFSET + 0x000100C8) +#define HDMI_LINK_H_LINE_1 (HDMI_ADDR_OFFSET + 0x000100CC) +#define HDMI_LINK_HSYNC_POL (HDMI_ADDR_OFFSET + 0x000100E0) +#define HDMI_LINK_VSYNC_POL (HDMI_ADDR_OFFSET + 0x000100E4) +#define HDMI_LINK_INT_PRO_MODE (HDMI_ADDR_OFFSET + 0x000100E8) +#define HDMI_LINK_SEND_START_0 (HDMI_ADDR_OFFSET + 0x000100F0) +#define HDMI_LINK_SEND_START_1 (HDMI_ADDR_OFFSET + 0x000100F4) +#define HDMI_LINK_SEND_END_0 (HDMI_ADDR_OFFSET + 0x00010100) +#define HDMI_LINK_SEND_END_1 (HDMI_ADDR_OFFSET + 0x00010104) +#define HDMI_LINK_SEND_END_2 (HDMI_ADDR_OFFSET + 0x00010108) +#define HDMI_LINK_V_BLANK_F0_0 (HDMI_ADDR_OFFSET + 0x00010110) +#define HDMI_LINK_V_BLANK_F0_1 (HDMI_ADDR_OFFSET + 0x00010114) +#define HDMI_LINK_V_BLANK_F1_0 (HDMI_ADDR_OFFSET + 0x00010118) +#define HDMI_LINK_V_BLANK_F1_1 (HDMI_ADDR_OFFSET + 0x0001011C) +#define HDMI_LINK_H_SYNC_START_0 (HDMI_ADDR_OFFSET + 0x00010120) +#define HDMI_LINK_H_SYNC_START_1 (HDMI_ADDR_OFFSET + 0x00010124) +#define HDMI_LINK_H_SYNC_END_0 (HDMI_ADDR_OFFSET + 0x00010128) +#define HDMI_LINK_H_SYNC_END_1 (HDMI_ADDR_OFFSET + 0x0001012C) +#define HDMI_LINK_V_SYNC_LINE_BEF_2_0 (HDMI_ADDR_OFFSET + 0x00010130) +#define HDMI_LINK_V_SYNC_LINE_BEF_2_1 (HDMI_ADDR_OFFSET + 0x00010134) +#define HDMI_LINK_V_SYNC_LINE_BEF_1_0 (HDMI_ADDR_OFFSET + 0x00010138) +#define HDMI_LINK_V_SYNC_LINE_BEF_1_1 (HDMI_ADDR_OFFSET + 0x0001013C) +#define HDMI_LINK_V_SYNC_LINE_AFT_2_0 (HDMI_ADDR_OFFSET + 0x00010140) +#define HDMI_LINK_V_SYNC_LINE_AFT_2_1 (HDMI_ADDR_OFFSET + 0x00010144) +#define HDMI_LINK_V_SYNC_LINE_AFT_1_0 (HDMI_ADDR_OFFSET + 0x00010148) +#define HDMI_LINK_V_SYNC_LINE_AFT_1_1 (HDMI_ADDR_OFFSET + 0x0001014C) +#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_2_0 (HDMI_ADDR_OFFSET + 0x00010150) +#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_2_1 (HDMI_ADDR_OFFSET + 0x00010154) +#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_1_0 (HDMI_ADDR_OFFSET + 0x00010158) +#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_1_1 (HDMI_ADDR_OFFSET + 0x0001015C) +#define HDMI_LINK_V_BLANK_F2_0 (HDMI_ADDR_OFFSET + 0x00010160) +#define HDMI_LINK_V_BLANK_F2_1 (HDMI_ADDR_OFFSET + 0x00010164) +#define HDMI_LINK_V_BLANK_F3_0 (HDMI_ADDR_OFFSET + 0x00010168) +#define HDMI_LINK_V_BLANK_F3_1 (HDMI_ADDR_OFFSET + 0x0001016C) +#define HDMI_LINK_V_BLANK_F4_0 (HDMI_ADDR_OFFSET + 0x00010170) +#define HDMI_LINK_V_BLANK_F4_1 (HDMI_ADDR_OFFSET + 0x00010174) +#define HDMI_LINK_V_BLANK_F5_0 (HDMI_ADDR_OFFSET + 0x00010178) +#define HDMI_LINK_V_BLANK_F5_1 (HDMI_ADDR_OFFSET + 0x0001017C) +#define HDMI_LINK_V_SYNC_LINE_AFT_3_0 (HDMI_ADDR_OFFSET + 0x00010180) +#define HDMI_LINK_V_SYNC_LINE_AFT_3_1 (HDMI_ADDR_OFFSET + 0x00010184) +#define HDMI_LINK_V_SYNC_LINE_AFT_4_0 (HDMI_ADDR_OFFSET + 0x00010188) +#define HDMI_LINK_V_SYNC_LINE_AFT_4_1 (HDMI_ADDR_OFFSET + 0x0001018C) +#define HDMI_LINK_V_SYNC_LINE_AFT_5_0 (HDMI_ADDR_OFFSET + 0x00010190) +#define HDMI_LINK_V_SYNC_LINE_AFT_5_1 (HDMI_ADDR_OFFSET + 0x00010194) +#define HDMI_LINK_V_SYNC_LINE_AFT_6_0 (HDMI_ADDR_OFFSET + 0x00010198) +#define HDMI_LINK_V_SYNC_LINE_AFT_6_1 (HDMI_ADDR_OFFSET + 0x0001019C) +#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_3_0 (HDMI_ADDR_OFFSET + 0x000101A0) +#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_3_1 (HDMI_ADDR_OFFSET + 0x000101A4) +#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_4_0 (HDMI_ADDR_OFFSET + 0x000101A8) +#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_4_1 (HDMI_ADDR_OFFSET + 0x000101AC) +#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_5_0 (HDMI_ADDR_OFFSET + 0x000101B0) +#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_5_1 (HDMI_ADDR_OFFSET + 0x000101B4) +#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_6_0 (HDMI_ADDR_OFFSET + 0x000101B8) +#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_6_1 (HDMI_ADDR_OFFSET + 0x000101BC) +#define HDMI_LINK_VACT_SPACE1_0 (HDMI_ADDR_OFFSET + 0x000101C0) +#define HDMI_LINK_VACT_SPACE1_1 (HDMI_ADDR_OFFSET + 0x000101C4) +#define HDMI_LINK_VACT_SPACE2_0 (HDMI_ADDR_OFFSET + 0x000101C8) +#define HDMI_LINK_VACT_SPACE2_1 (HDMI_ADDR_OFFSET + 0x000101CC) +#define HDMI_LINK_VACT_SPACE3_0 (HDMI_ADDR_OFFSET + 0x000101D0) +#define HDMI_LINK_VACT_SPACE3_1 (HDMI_ADDR_OFFSET + 0x000101D4) +#define HDMI_LINK_VACT_SPACE4_0 (HDMI_ADDR_OFFSET + 0x000101D8) +#define HDMI_LINK_VACT_SPACE4_1 (HDMI_ADDR_OFFSET + 0x000101DC) +#define HDMI_LINK_VACT_SPACE5_0 (HDMI_ADDR_OFFSET + 0x000101E0) +#define HDMI_LINK_VACT_SPACE5_1 (HDMI_ADDR_OFFSET + 0x000101E4) +#define HDMI_LINK_VACT_SPACE6_0 (HDMI_ADDR_OFFSET + 0x000101E8) +#define HDMI_LINK_VACT_SPACE6_1 (HDMI_ADDR_OFFSET + 0x000101EC) + +#define HDMI_LINK_CSC_MUX (HDMI_ADDR_OFFSET + 0x000101F0) +#define HDMI_LINK_SYNC_GEN_MUX (HDMI_ADDR_OFFSET + 0x000101F4) + +#define HDMI_LINK_GCP_CON (HDMI_ADDR_OFFSET + 0x00010200) +#define HDMI_LINK_GCP_BYTE1 (HDMI_ADDR_OFFSET + 0x00010210) +#define HDMI_LINK_GCP_BYTE2 (HDMI_ADDR_OFFSET + 0x00010214) +#define HDMI_LINK_GCP_BYTE3 (HDMI_ADDR_OFFSET + 0x00010218) +#define HDMI_LINK_ASP_CON (HDMI_ADDR_OFFSET + 0x00010300) +#define HDMI_LINK_ASP_SP_FLAT (HDMI_ADDR_OFFSET + 0x00010304) +#define HDMI_LINK_ASP_CHCFG0 (HDMI_ADDR_OFFSET + 0x00010310) +#define HDMI_LINK_ASP_CHCFG1 (HDMI_ADDR_OFFSET + 0x00010314) +#define HDMI_LINK_ASP_CHCFG2 (HDMI_ADDR_OFFSET + 0x00010318) +#define HDMI_LINK_ASP_CHCFG3 (HDMI_ADDR_OFFSET + 0x0001031C) +#define HDMI_LINK_ACR_CON (HDMI_ADDR_OFFSET + 0x00010400) +#define HDMI_LINK_ACR_MCTS0 (HDMI_ADDR_OFFSET + 0x00010410) +#define HDMI_LINK_ACR_MCTS1 (HDMI_ADDR_OFFSET + 0x00010414) +#define HDMI_LINK_ACR_MCTS2 (HDMI_ADDR_OFFSET + 0x00010418) +#define HDMI_LINK_ACR_N0 (HDMI_ADDR_OFFSET + 0x00010430) +#define HDMI_LINK_ACR_N1 (HDMI_ADDR_OFFSET + 0x00010434) +#define HDMI_LINK_ACR_N2 (HDMI_ADDR_OFFSET + 0x00010438) +#define HDMI_LINK_ACP_CON (HDMI_ADDR_OFFSET + 0x00010500) +#define HDMI_LINK_ACP_TYPE (HDMI_ADDR_OFFSET + 0x00010514) +#define HDMI_LINK_ACP_DATAX (HDMI_ADDR_OFFSET + 0x00010520) +#define HDMI_LINK_ISRC_CON (HDMI_ADDR_OFFSET + 0x00010600) +#define HDMI_LINK_ISRC1_HEADER1 (HDMI_ADDR_OFFSET + 0x00010614) +#define HDMI_LINK_ISRC1_DATAX (HDMI_ADDR_OFFSET + 0x00010620) +#define HDMI_LINK_ISRC2_DATAX (HDMI_ADDR_OFFSET + 0x000106A0) +#define HDMI_LINK_AVI_CON (HDMI_ADDR_OFFSET + 0x00010700) +#define HDMI_LINK_AVI_HEADER0 (HDMI_ADDR_OFFSET + 0x00010710) +#define HDMI_LINK_AVI_HEADER1 (HDMI_ADDR_OFFSET + 0x00010714) +#define HDMI_LINK_AVI_HEADER2 (HDMI_ADDR_OFFSET + 0x00010718) +#define HDMI_LINK_AVI_CHECK_SUM (HDMI_ADDR_OFFSET + 0x0001071C) +#define HDMI_LINK_AVI_BYTEX (HDMI_ADDR_OFFSET + 0x00010720) +#define HDMI_LINK_AVI_BYTE00 (HDMI_ADDR_OFFSET + 0x00010720) +#define HDMI_LINK_AVI_BYTE01 (HDMI_ADDR_OFFSET + 0x00010724) +#define HDMI_LINK_AVI_BYTE02 (HDMI_ADDR_OFFSET + 0x00010728) +#define HDMI_LINK_AVI_BYTE03 (HDMI_ADDR_OFFSET + 0x0001073C) +#define HDMI_LINK_AVI_BYTE04 (HDMI_ADDR_OFFSET + 0x00010730) +#define HDMI_LINK_AVI_BYTE05 (HDMI_ADDR_OFFSET + 0x00010734) +#define HDMI_LINK_AVI_BYTE06 (HDMI_ADDR_OFFSET + 0x00010738) +#define HDMI_LINK_AVI_BYTE07 (HDMI_ADDR_OFFSET + 0x0001074C) +#define HDMI_LINK_AVI_BYTE08 (HDMI_ADDR_OFFSET + 0x00010740) +#define HDMI_LINK_AVI_BYTE09 (HDMI_ADDR_OFFSET + 0x00010744) +#define HDMI_LINK_AVI_BYTE10 (HDMI_ADDR_OFFSET + 0x00010748) +#define HDMI_LINK_AVI_BYTE11 (HDMI_ADDR_OFFSET + 0x0001074C) +#define HDMI_LINK_AVI_BYTE12 (HDMI_ADDR_OFFSET + 0x00010750) +#define HDMI_LINK_AUI_CON (HDMI_ADDR_OFFSET + 0x00010800) +#define HDMI_LINK_AUI_HEADER0 (HDMI_ADDR_OFFSET + 0x00010810) +#define HDMI_LINK_AUI_HEADER1 (HDMI_ADDR_OFFSET + 0x00010814) +#define HDMI_LINK_AUI_HEADER2 (HDMI_ADDR_OFFSET + 0x00010818) +#define HDMI_LINK_AUI_CHECK_SUM (HDMI_ADDR_OFFSET + 0x0001081C) +#define HDMI_LINK_AUI_BYTEX (HDMI_ADDR_OFFSET + 0x00010820) +#define HDMI_LINK_MPG_CON (HDMI_ADDR_OFFSET + 0x00010900) +#define HDMI_LINK_MPG_CHECK_SUM (HDMI_ADDR_OFFSET + 0x0001091C) +#define HDMI_LINK_MPG_DATAX (HDMI_ADDR_OFFSET + 0x00010920) +#define HDMI_LINK_SPD_CON (HDMI_ADDR_OFFSET + 0x00010A00) +#define HDMI_LINK_SPD_HEADER0 (HDMI_ADDR_OFFSET + 0x00010A10) +#define HDMI_LINK_SPD_HEADER1 (HDMI_ADDR_OFFSET + 0x00010A14) +#define HDMI_LINK_SPD_HEADER2 (HDMI_ADDR_OFFSET + 0x00010A18) +#define HDMI_LINK_SPD_DATAX (HDMI_ADDR_OFFSET + 0x00010A20) +#define HDMI_LINK_GAMUT_CON (HDMI_ADDR_OFFSET + 0x00010B00) +#define HDMI_LINK_GAMUT_HEADER0 (HDMI_ADDR_OFFSET + 0x00010B10) +#define HDMI_LINK_GAMUT_HEADER1 (HDMI_ADDR_OFFSET + 0x00010B14) +#define HDMI_LINK_GAMUT_HEADER2 (HDMI_ADDR_OFFSET + 0x00010B18) +#define HDMI_LINK_GAMUT_METADATAX (HDMI_ADDR_OFFSET + 0x00010B20) +#define HDMI_LINK_VSI_CON (HDMI_ADDR_OFFSET + 0x00010C00) +#define HDMI_LINK_VSI_HEADER0 (HDMI_ADDR_OFFSET + 0x00010C10) +#define HDMI_LINK_VSI_HEADER1 (HDMI_ADDR_OFFSET + 0x00010C14) +#define HDMI_LINK_VSI_HEADER2 (HDMI_ADDR_OFFSET + 0x00010C18) +#define HDMI_LINK_VSI_DATAX (HDMI_ADDR_OFFSET + 0x00010C20) +#define HDMI_LINK_VSI_DATA00 (HDMI_ADDR_OFFSET + 0x00010C20) +#define HDMI_LINK_VSI_DATA01 (HDMI_ADDR_OFFSET + 0x00010C24) +#define HDMI_LINK_VSI_DATA02 (HDMI_ADDR_OFFSET + 0x00010C28) +#define HDMI_LINK_VSI_DATA03 (HDMI_ADDR_OFFSET + 0x00010C2C) +#define HDMI_LINK_VSI_DATA04 (HDMI_ADDR_OFFSET + 0x00010C30) +#define HDMI_LINK_VSI_DATA05 (HDMI_ADDR_OFFSET + 0x00010C34) +#define HDMI_LINK_VSI_DATA06 (HDMI_ADDR_OFFSET + 0x00010C38) +#define HDMI_LINK_VSI_DATA07 (HDMI_ADDR_OFFSET + 0x00010C3C) +#define HDMI_LINK_VSI_DATA08 (HDMI_ADDR_OFFSET + 0x00010C40) +#define HDMI_LINK_VSI_DATA09 (HDMI_ADDR_OFFSET + 0x00010C44) +#define HDMI_LINK_VSI_DATA10 (HDMI_ADDR_OFFSET + 0x00010C48) +#define HDMI_LINK_VSI_DATA11 (HDMI_ADDR_OFFSET + 0x00010c4c) +#define HDMI_LINK_VSI_DATA12 (HDMI_ADDR_OFFSET + 0x00010C50) +#define HDMI_LINK_VSI_DATA13 (HDMI_ADDR_OFFSET + 0x00010C54) +#define HDMI_LINK_VSI_DATA14 (HDMI_ADDR_OFFSET + 0x00010C58) +#define HDMI_LINK_VSI_DATA15 (HDMI_ADDR_OFFSET + 0x00010C5c) +#define HDMI_LINK_VSI_DATA16 (HDMI_ADDR_OFFSET + 0x00010C60) +#define HDMI_LINK_VSI_DATA17 (HDMI_ADDR_OFFSET + 0x00010C64) +#define HDMI_LINK_VSI_DATA18 (HDMI_ADDR_OFFSET + 0x00010C68) +#define HDMI_LINK_VSI_DATA19 (HDMI_ADDR_OFFSET + 0x00010C6c) +#define HDMI_LINK_VSI_DATA20 (HDMI_ADDR_OFFSET + 0x00010C70) +#define HDMI_LINK_VSI_DATA21 (HDMI_ADDR_OFFSET + 0x00010c74) +#define HDMI_LINK_VSI_DATA22 (HDMI_ADDR_OFFSET + 0x00010C78) +#define HDMI_LINK_VSI_DATA23 (HDMI_ADDR_OFFSET + 0x00010C7c) +#define HDMI_LINK_VSI_DATA24 (HDMI_ADDR_OFFSET + 0x00010C80) +#define HDMI_LINK_VSI_DATA25 (HDMI_ADDR_OFFSET + 0x00010C84) +#define HDMI_LINK_VSI_DATA26 (HDMI_ADDR_OFFSET + 0x00010C88) +#define HDMI_LINK_VSI_DATA27 (HDMI_ADDR_OFFSET + 0x00010C8C) +#define HDMI_LINK_DC_CONTROL (HDMI_ADDR_OFFSET + 0x00010D00) +#define HDMI_LINK_VIDEO_PATTERN_GEN (HDMI_ADDR_OFFSET + 0x00010D04) +#define HDMI_LINK_AN_SEED_SEL (HDMI_ADDR_OFFSET + 0x00010E48) +#define HDMI_LINK_AN_SEED_0 (HDMI_ADDR_OFFSET + 0x00010E58) +#define HDMI_LINK_AN_SEED_1 (HDMI_ADDR_OFFSET + 0x00010E5C) +#define HDMI_LINK_AN_SEED_2 (HDMI_ADDR_OFFSET + 0x00010E60) +#define HDMI_LINK_AN_SEED_3 (HDMI_ADDR_OFFSET + 0x00010E64) +#define HDMI_LINK_HDCP_SHA1_X (HDMI_ADDR_OFFSET + 0x00017000) + +#define HDMI_LINK_HDCP_SHA1_0_0 (HDMI_LINK_HDCP_SHA1_x + 0x00) +#define HDMI_LINK_HDCP_SHA1_0_1 (HDMI_LINK_HDCP_SHA1_0_0 + 0x04) +#define HDMI_LINK_HDCP_SHA1_0_2 (HDMI_LINK_HDCP_SHA1_0_0 + 0x08) +#define HDMI_LINK_HDCP_SHA1_0_3 (HDMI_LINK_HDCP_SHA1_0_0 + 0x0C) +#define HDMI_LINK_HDCP_SHA1_1_0 (HDMI_LINK_HDCP_SHA1_x + 0x10) +#define HDMI_LINK_HDCP_SHA1_1_1 (HDMI_LINK_HDCP_SHA1_1_0 + 0x04) +#define HDMI_LINK_HDCP_SHA1_1_2 (HDMI_LINK_HDCP_SHA1_1_0 + 0x08) +#define HDMI_LINK_HDCP_SHA1_1_3 (HDMI_LINK_HDCP_SHA1_1_0 + 0x0C) +#define HDMI_LINK_HDCP_SHA1_2_0 (HDMI_LINK_HDCP_SHA1_x + 0x20) +#define HDMI_LINK_HDCP_SHA1_2_1 (HDMI_LINK_HDCP_SHA1_2_0 + 0x04) +#define HDMI_LINK_HDCP_SHA1_2_2 (HDMI_LINK_HDCP_SHA1_2_0 + 0x08) +#define HDMI_LINK_HDCP_SHA1_2_3 (HDMI_LINK_HDCP_SHA1_2_0 + 0x0C) +#define HDMI_LINK_HDCP_SHA1_3_0 (HDMI_LINK_HDCP_SHA1_x + 0x30) +#define HDMI_LINK_HDCP_SHA1_3_1 (HDMI_LINK_HDCP_SHA1_3_0 + 0x04) +#define HDMI_LINK_HDCP_SHA1_3_2 (HDMI_LINK_HDCP_SHA1_3_0 + 0x08) +#define HDMI_LINK_HDCP_SHA1_3_3 (HDMI_LINK_HDCP_SHA1_3_0 + 0x0C) +#define HDMI_LINK_HDCP_SHA1_4_0 (HDMI_LINK_HDCP_SHA1_x + 0x40) +#define HDMI_LINK_HDCP_SHA1_4_1 (HDMI_LINK_HDCP_SHA1_4_0 + 0x04) +#define HDMI_LINK_HDCP_SHA1_4_2 (HDMI_LINK_HDCP_SHA1_4_0 + 0x08) +#define HDMI_LINK_HDCP_SHA1_4_3 (HDMI_LINK_HDCP_SHA1_4_0 + 0x0C) + +#define HDMI_LINK_HDCP_KSV_LIST_X (HDMI_ADDR_OFFSET + 0x00017050) + +#define HDMI_LINK_HDCP_KSV_0_0 (HDMI_LINK_HDCP_KSV_LIST_X + 0x00) +#define HDMI_LINK_HDCP_KSV_0_1 (HDMI_LINK_HDCP_KSV_LIST_X + 0x04) +#define HDMI_LINK_HDCP_KSV_0_2 (HDMI_LINK_HDCP_KSV_LIST_X + 0x08) +#define HDMI_LINK_HDCP_KSV_0_3 (HDMI_LINK_HDCP_KSV_LIST_X + 0x0C) +#define HDMI_LINK_HDCP_KSV_1_0 (HDMI_LINK_HDCP_KSV_LIST_X + 0x10) +#define HDMI_LINK_HDCP_KSV_1_1 (HDMI_LINK_HDCP_KSV_LIST_X + 0x14) + +#define HDMI_LINK_HDCP_KSV_LIST_0_0 (HDMI_LINK_HDCP_KSV_LIST_X + 0x00) +#define HDMI_LINK_HDCP_KSV_LIST_0_1 (HDMI_LINK_HDCP_KSV_LIST_X + 0x04) +#define HDMI_LINK_HDCP_KSV_LIST_0_2 (HDMI_LINK_HDCP_KSV_LIST_X + 0x08) +#define HDMI_LINK_HDCP_KSV_LIST_0_3 (HDMI_LINK_HDCP_KSV_LIST_X + 0x0C) +#define HDMI_LINK_HDCP_KSV_LIST_1_0 (HDMI_LINK_HDCP_KSV_LIST_X + 0x10) +#define HDMI_LINK_HDCP_KSV_LIST_1_1 (HDMI_LINK_HDCP_KSV_LIST_X + 0x14) + +#define HDMI_LINK_HDCP_KSV_LIST_CON (HDMI_ADDR_OFFSET + 0x00017064) +#define HDMI_LINK_HDCP_SHA_RESULT (HDMI_ADDR_OFFSET + 0x00017070) +#define HDMI_LINK_HDCP_CTRL1 (HDMI_ADDR_OFFSET + 0x00017080) +#define HDMI_LINK_HDCP_CTRL2 (HDMI_ADDR_OFFSET + 0x00017084) +#define HDMI_LINK_HDCP_CHECK_RESULT (HDMI_ADDR_OFFSET + 0x00017090) +#define HDMI_LINK_HDCP_BKSV_X (HDMI_ADDR_OFFSET + 0x000170A0) + +#define HDMI_LINK_HDCP_BKSV0_0 (HDMI_ADDR_OFFSET + 0x000170A0) +#define HDMI_LINK_HDCP_BKSV0_1 (HDMI_ADDR_OFFSET + 0x000170A4) +#define HDMI_LINK_HDCP_BKSV0_2 (HDMI_ADDR_OFFSET + 0x000170A8) +#define HDMI_LINK_HDCP_BKSV0_3 (HDMI_ADDR_OFFSET + 0x000170AC) +#define HDMI_LINK_HDCP_BKSV1 (HDMI_ADDR_OFFSET + 0x000170B0) + +#define HDMI_LINK_HDCP_AKSV_X (HDMI_ADDR_OFFSET + 0x000170C0) +#define HDMI_LINK_HDCP_AN_X (HDMI_ADDR_OFFSET + 0x000170E0) +#define HDMI_LINK_HDCP_BCAPS (HDMI_ADDR_OFFSET + 0x00017100) +#define HDMI_LINK_HDCP_BSTATUS_0 (HDMI_ADDR_OFFSET + 0x00017110) +#define HDMI_LINK_HDCP_BSTATUS_1 (HDMI_ADDR_OFFSET + 0x00017114) +#define HDMI_LINK_HDCP_RI_0 (HDMI_ADDR_OFFSET + 0x00017140) +#define HDMI_LINK_HDCP_RI_1 (HDMI_ADDR_OFFSET + 0x00017144) + +#define HDMI_LINK_HDCP_OFFSET_TX_0 (HDMI_ADDR_OFFSET + 0x00017160) +#define HDMI_LINK_HDCP_OFFSET_TX_1 (HDMI_ADDR_OFFSET + 0x00017164) +#define HDMI_LINK_HDCP_OFFSET_TX_2 (HDMI_ADDR_OFFSET + 0x00017168) +#define HDMI_LINK_HDCP_OFFSET_TX_3 (HDMI_ADDR_OFFSET + 0x0001716C) +#define HDMI_LINK_HDCP_CYCLE_AA (HDMI_ADDR_OFFSET + 0x00017170) + +#define HDMI_LINK_HDCP_I2C_INT (HDMI_ADDR_OFFSET + 0x00017180) +#define HDMI_LINK_HDCP_AN_INT (HDMI_ADDR_OFFSET + 0x00017190) +#define HDMI_LINK_HDCP_WATCHDOG_INT (HDMI_ADDR_OFFSET + 0x000171A0) +#define HDMI_LINK_HDCP_RI_INT (HDMI_ADDR_OFFSET + 0x000171B0) +#define HDMI_LINK_HDCP_RI_COMPARE_0 (HDMI_ADDR_OFFSET + 0x000171D0) +#define HDMI_LINK_HDCP_RI_COMPARE_1 (HDMI_ADDR_OFFSET + 0x000171D4) + +#define HDMI_LINK_HDCP_RI_INT (HDMI_ADDR_OFFSET + 0x000171B0) +#define HDMI_LINK_HDCP_RI_COMPARE_0 (HDMI_ADDR_OFFSET + 0x000171D0) +#define HDMI_LINK_HDCP_RI_COMPARE_1 (HDMI_ADDR_OFFSET + 0x000171D4) + +#define HDMI_LINK_HDCP_FRAME_COUNT (HDMI_ADDR_OFFSET + 0x000171E0) +#define HDMI_LINK_RGB_ROUND_EN (HDMI_ADDR_OFFSET + 0x0001D500) +#define HDMI_LINK_VACT_SPACE_R_0 (HDMI_ADDR_OFFSET + 0x0001D504) +#define HDMI_LINK_VACT_SPACE_R_1 (HDMI_ADDR_OFFSET + 0x0001D508) +#define HDMI_LINK_VACT_SPACE_G_0 (HDMI_ADDR_OFFSET + 0x0001D50C) +#define HDMI_LINK_VACT_SPACE_G_1 (HDMI_ADDR_OFFSET + 0x0001D510) +#define HDMI_LINK_VACT_SPACE_B_0 (HDMI_ADDR_OFFSET + 0x0001D514) +#define HDMI_LINK_VACT_SPACE_B_1 (HDMI_ADDR_OFFSET + 0x0001D518) +#define HDMI_LINK_BLUE_SCREEN_R_0 (HDMI_ADDR_OFFSET + 0x0001D520) +#define HDMI_LINK_BLUE_SCREEN_R_1 (HDMI_ADDR_OFFSET + 0x0001D524) +#define HDMI_LINK_BLUE_SCREEN_G_0 (HDMI_ADDR_OFFSET + 0x0001D528) +#define HDMI_LINK_BLUE_SCREEN_G_1 (HDMI_ADDR_OFFSET + 0x0001D52C) +#define HDMI_LINK_BLUE_SCREEN_B_0 (HDMI_ADDR_OFFSET + 0x0001D530) +#define HDMI_LINK_BLUE_SCREEN_B_1 (HDMI_ADDR_OFFSET + 0x0001D534) +#define HDMI_LINK_AES_START (HDMI_ADDR_OFFSET + 0x00020000) +#define HDMI_LINK_AES_DATA_SIZE_L (HDMI_ADDR_OFFSET + 0x00020020) +#define HDMI_LINK_AES_DATA_SIZE_H (HDMI_ADDR_OFFSET + 0x00020024) +#define HDMI_LINK_AES_DATA (HDMI_ADDR_OFFSET + 0x00020040) +#define HDMI_LINK_SPDIFIN_CLK_CTRL (HDMI_ADDR_OFFSET + 0x00030000) +#define HDMI_LINK_SPDIFIN_OP_CTRL (HDMI_ADDR_OFFSET + 0x00030004) +#define HDMI_LINK_SPDIFIN_IRQ_MASK (HDMI_ADDR_OFFSET + 0x00030008) +#define HDMI_LINK_SPDIFIN_IRQ_STATUS (HDMI_ADDR_OFFSET + 0x0003000C) +#define HDMI_LINK_SPDIFIN_CONFIG_1 (HDMI_ADDR_OFFSET + 0x00030010) +#define HDMI_LINK_SPDIFIN_CONFIG_2 (HDMI_ADDR_OFFSET + 0x00030014) +#define HDMI_LINK_SPDIFIN_USER_VALUE_1 (HDMI_ADDR_OFFSET + 0x00030020) +#define HDMI_LINK_SPDIFIN_USER_VALUE_2 (HDMI_ADDR_OFFSET + 0x00030024) +#define HDMI_LINK_SPDIFIN_USER_VALUE_3 (HDMI_ADDR_OFFSET + 0x00030028) +#define HDMI_LINK_SPDIFIN_USER_VALUE_4 (HDMI_ADDR_OFFSET + 0x0003002C) +#define HDMI_LINK_SPDIFIN_CH_STATUS_0_1 (HDMI_ADDR_OFFSET + 0x00030030) +#define HDMI_LINK_SPDIFIN_CH_STATUS_0_2 (HDMI_ADDR_OFFSET + 0x00030034) +#define HDMI_LINK_SPDIFIN_CH_STATUS_0_3 (HDMI_ADDR_OFFSET + 0x00030038) +#define HDMI_LINK_SPDIFIN_CH_STATUS_0_4 (HDMI_ADDR_OFFSET + 0x0003003C) +#define HDMI_LINK_SPDIFIN_CH_STATUS_1 (HDMI_ADDR_OFFSET + 0x00030040) +#define HDMI_LINK_SPDIFIN_FRAME_PERIOD_1 (HDMI_ADDR_OFFSET + 0x00030048) +#define HDMI_LINK_SPDIFIN_FRAME_PERIOD_2 (HDMI_ADDR_OFFSET + 0x0003004C) +#define HDMI_LINK_SPDIFIN_PC_INFO_1 (HDMI_ADDR_OFFSET + 0x00030050) +#define HDMI_LINK_SPDIFIN_PC_INFO_2 (HDMI_ADDR_OFFSET + 0x00030054) +#define HDMI_LINK_SPDIFIN_PD_INFO_1 (HDMI_ADDR_OFFSET + 0x00030058) +#define HDMI_LINK_SPDIFIN_PD_INFO_2 (HDMI_ADDR_OFFSET + 0x0003005C) +#define HDMI_LINK_SPDIFIN_DATA_BUF_0_1 (HDMI_ADDR_OFFSET + 0x00030060) +#define HDMI_LINK_SPDIFIN_DATA_BUF_0_2 (HDMI_ADDR_OFFSET + 0x00030064) +#define HDMI_LINK_SPDIFIN_DATA_BUF_0_3 (HDMI_ADDR_OFFSET + 0x00030068) +#define HDMI_LINK_SPDIFIN_USER_BUF_0 (HDMI_ADDR_OFFSET + 0x0003006C) +#define HDMI_LINK_SPDIFIN_DATA_BUF_1_1 (HDMI_ADDR_OFFSET + 0x00030070) +#define HDMI_LINK_SPDIFIN_DATA_BUF_1_2 (HDMI_ADDR_OFFSET + 0x00030074) +#define HDMI_LINK_SPDIFIN_DATA_BUF_1_3 (HDMI_ADDR_OFFSET + 0x00030078) +#define HDMI_LINK_SPDIFIN_USER_BUF_1 (HDMI_ADDR_OFFSET + 0x0003007C) +#define HDMI_LINK_I2S_CLK_CON (HDMI_ADDR_OFFSET + 0x00040000) +#define HDMI_LINK_I2S_CON_1 (HDMI_ADDR_OFFSET + 0x00040004) +#define HDMI_LINK_I2S_CON_2 (HDMI_ADDR_OFFSET + 0x00040008) +#define HDMI_LINK_I2S_PIN_SEL_0 (HDMI_ADDR_OFFSET + 0x0004000C) +#define HDMI_LINK_I2S_PIN_SEL_1 (HDMI_ADDR_OFFSET + 0x00040010) +#define HDMI_LINK_I2S_PIN_SEL_2 (HDMI_ADDR_OFFSET + 0x00040014) +#define HDMI_LINK_I2S_PIN_SEL_3 (HDMI_ADDR_OFFSET + 0x00040018) +#define HDMI_LINK_I2S_DSD_CON (HDMI_ADDR_OFFSET + 0x0004001C) +#define HDMI_LINK_I2S_MUX_CON (HDMI_ADDR_OFFSET + 0x00040020) +#define HDMI_LINK_I2S_CH_ST_CON (HDMI_ADDR_OFFSET + 0x00040024) +#define HDMI_LINK_I2S_CH_ST_0 (HDMI_ADDR_OFFSET + 0x00040028) +#define HDMI_LINK_I2S_CH_ST_1 (HDMI_ADDR_OFFSET + 0x0004002C) +#define HDMI_LINK_I2S_CH_ST_2 (HDMI_ADDR_OFFSET + 0x00040030) +#define HDMI_LINK_I2S_CH_ST_3 (HDMI_ADDR_OFFSET + 0x00040034) +#define HDMI_LINK_I2S_CH_ST_4 (HDMI_ADDR_OFFSET + 0x00040038) +#define HDMI_LINK_I2S_CH_ST_SH_0 (HDMI_ADDR_OFFSET + 0x0004003C) +#define HDMI_LINK_I2S_CH_ST_SH_1 (HDMI_ADDR_OFFSET + 0x00040040) +#define HDMI_LINK_I2S_CH_ST_SH_2 (HDMI_ADDR_OFFSET + 0x00040044) +#define HDMI_LINK_I2S_CH_ST_SH_3 (HDMI_ADDR_OFFSET + 0x00040048) +#define HDMI_LINK_I2S_CH_ST_SH_4 (HDMI_ADDR_OFFSET + 0x0004004C) +#define HDMI_LINK_I2S_VD_DATA (HDMI_ADDR_OFFSET + 0x00040050) +#define HDMI_LINK_I2S_MUX_CH (HDMI_ADDR_OFFSET + 0x00040054) +#define HDMI_LINK_I2S_MUX_CUV (HDMI_ADDR_OFFSET + 0x00040058) +#define HDMI_LINK_I2S_CH0_L_0 (HDMI_ADDR_OFFSET + 0x00040064) +#define HDMI_LINK_I2S_CH0_L_1 (HDMI_ADDR_OFFSET + 0x00040068) +#define HDMI_LINK_I2S_CH0_L_2 (HDMI_ADDR_OFFSET + 0x0004006C) +#define HDMI_LINK_I2S_CH0_R_0 (HDMI_ADDR_OFFSET + 0x00040074) +#define HDMI_LINK_I2S_CH0_R_1 (HDMI_ADDR_OFFSET + 0x00040078) +#define HDMI_LINK_I2S_CH0_R_2 (HDMI_ADDR_OFFSET + 0x0004007C) +#define HDMI_LINK_I2S_CH0_R_3 (HDMI_ADDR_OFFSET + 0x00040080) +#define HDMI_LINK_I2S_CH1_L_0 (HDMI_ADDR_OFFSET + 0x00040084) +#define HDMI_LINK_I2S_CH1_L_1 (HDMI_ADDR_OFFSET + 0x00040088) +#define HDMI_LINK_I2S_CH1_L_2 (HDMI_ADDR_OFFSET + 0x0004008C) +#define HDMI_LINK_I2S_CH1_L_3 (HDMI_ADDR_OFFSET + 0x00040090) +#define HDMI_LINK_I2S_CH1_R_0 (HDMI_ADDR_OFFSET + 0x00040094) +#define HDMI_LINK_I2S_CH1_R_1 (HDMI_ADDR_OFFSET + 0x00040098) +#define HDMI_LINK_I2S_CH1_R_2 (HDMI_ADDR_OFFSET + 0x0004009C) +#define HDMI_LINK_I2S_CH1_R_3 (HDMI_ADDR_OFFSET + 0x000400A0) +#define HDMI_LINK_I2S_CH2_L_0 (HDMI_ADDR_OFFSET + 0x000400A4) +#define HDMI_LINK_I2S_CH2_L_1 (HDMI_ADDR_OFFSET + 0x000400A8) +#define HDMI_LINK_I2S_CH2_L_2 (HDMI_ADDR_OFFSET + 0x000400AC) +#define HDMI_LINK_I2S_CH2_L_3 (HDMI_ADDR_OFFSET + 0x000400B0) +#define HDMI_LINK_I2S_CH2_R_0 (HDMI_ADDR_OFFSET + 0x000400B4) +#define HDMI_LINK_I2S_CH2_R_1 (HDMI_ADDR_OFFSET + 0x000400B8) +#define HDMI_LINK_I2S_CH2_R_2 (HDMI_ADDR_OFFSET + 0x000400BC) +#define HDMI_LINK_I2S_CH2_R_3 (HDMI_ADDR_OFFSET + 0x000400C0) +#define HDMI_LINK_I2S_CH3_L_0 (HDMI_ADDR_OFFSET + 0x000400C4) +#define HDMI_LINK_I2S_CH3_L_1 (HDMI_ADDR_OFFSET + 0x000400C8) +#define HDMI_LINK_I2S_CH3_L_2 (HDMI_ADDR_OFFSET + 0x000400CC) +#define HDMI_LINK_I2S_CH3_R_0 (HDMI_ADDR_OFFSET + 0x000400D0) +#define HDMI_LINK_I2S_CH3_R_1 (HDMI_ADDR_OFFSET + 0x000400D4) +#define HDMI_LINK_I2S_CH3_R_2 (HDMI_ADDR_OFFSET + 0x000400D8) +#define HDMI_LINK_I2S_CUV_L_R (HDMI_ADDR_OFFSET + 0x000400DC) + +#define HDMI_CEC_TX_STATUS_0 (OTHER_ADDR_OFFSET + 0x00000000) +#define HDMI_CEC_TX_STATUS_1 (OTHER_ADDR_OFFSET + 0x00000004) +#define HDMI_CEC_RX_STATUS_0 (OTHER_ADDR_OFFSET + 0x00000008) +#define HDMI_CEC_RX_STATUS_1 (OTHER_ADDR_OFFSET + 0x0000000C) +#define HDMI_CEC_INTR_MASK (OTHER_ADDR_OFFSET + 0x00000010) +#define HDMI_CEC_INTR_CLEAR (OTHER_ADDR_OFFSET + 0x00000014) +#define HDMI_CEC_LOGIC_ADDR (OTHER_ADDR_OFFSET + 0x00000020) +#define HDMI_CEC_DIVISOR_0 (OTHER_ADDR_OFFSET + 0x00000030) +#define HDMI_CEC_DIVISOR_1 (OTHER_ADDR_OFFSET + 0x00000034) +#define HDMI_CEC_DIVISOR_2 (OTHER_ADDR_OFFSET + 0x00000038) +#define HDMI_CEC_DIVISOR_3 (OTHER_ADDR_OFFSET + 0x0000003C) +#define HDMI_CEC_TX_CTRL (OTHER_ADDR_OFFSET + 0x00000040) +#define HDMI_CEC_TX_BYTE_NUM (OTHER_ADDR_OFFSET + 0x00000044) +#define HDMI_CEC_TX_STATUS_2 (OTHER_ADDR_OFFSET + 0x00000060) +#define HDMI_CEC_TX_STATUS_3 (OTHER_ADDR_OFFSET + 0x00000064) +#define HDMI_CEC_TX_BUFFER_x (OTHER_ADDR_OFFSET + 0x00000080) +#define HDMI_CEC_TX_BUFFER00 (OTHER_ADDR_OFFSET + 0x00000080) +#define HDMI_CEC_RX_CTRL (OTHER_ADDR_OFFSET + 0x000000C0) +#define HDMI_CEC_RX_STATUS_2 (OTHER_ADDR_OFFSET + 0x000000E0) +#define HDMI_CEC_RX_STATUS_3 (OTHER_ADDR_OFFSET + 0x000000E4) +#define HDMI_CEC_RX_BUFFER_x (OTHER_ADDR_OFFSET + 0x00000100) +#define HDMI_CEC_FILTER_CTRL (OTHER_ADDR_OFFSET + 0x00000180) +#define HDMI_CEC_FILTER_TH (OTHER_ADDR_OFFSET + 0x00000184) + +#ifdef CONFIG_MACH_S5P6818 +#define HDMI_PHY_OFFSET \ + (PHY_BASEADDR_HDMI_PHY_MODULE - PHY_BASEADDR_HDMI_MODULE) +#else +#define HDMI_PHY_OFFSET 0x400 +#endif + +#define HDMI_PHY_REG00 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000000) +#define HDMI_PHY_REG04 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000004) +#define HDMI_PHY_REG08 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000008) +#define HDMI_PHY_REG0C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000000C) +#define HDMI_PHY_REG10 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000010) +#define HDMI_PHY_REG14 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000014) +#define HDMI_PHY_REG18 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000018) +#define HDMI_PHY_REG1C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000001C) +#define HDMI_PHY_REG20 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000020) +#define HDMI_PHY_REG24 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000024) +#define HDMI_PHY_REG28 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000028) +#define HDMI_PHY_REG2C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000002C) +#define HDMI_PHY_REG30 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000030) +#define HDMI_PHY_REG34 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000034) +#define HDMI_PHY_REG38 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000038) +#define HDMI_PHY_REG3C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000003C) +#define HDMI_PHY_REG40 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000040) +#define HDMI_PHY_REG44 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000044) +#define HDMI_PHY_REG48 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000048) +#define HDMI_PHY_REG4C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000004C) +#define HDMI_PHY_REG50 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000050) +#define HDMI_PHY_REG54 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000054) +#define HDMI_PHY_REG58 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000058) +#define HDMI_PHY_REG5C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000005C) +#define HDMI_PHY_REG60 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000060) +#define HDMI_PHY_REG64 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000064) +#define HDMI_PHY_REG68 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000068) +#define HDMI_PHY_REG6C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000006C) +#define HDMI_PHY_REG70 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000070) +#define HDMI_PHY_REG74 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000074) +#define HDMI_PHY_REG78 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000078) +#define HDMI_PHY_REG7C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000007C) +#define HDMI_PHY_REG80 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000080) +#define HDMI_PHY_REG84 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000084) +#define HDMI_PHY_REG88 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000088) +#define HDMI_PHY_REG8C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000008C) +#define HDMI_PHY_REG90 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000090) + +enum hdmi_reset { + i_nRST = 0, + i_nRST_VIDEO = 1, + i_nRST_SPDIF = 2, + i_nRST_TMDS = 3, + i_nRST_PHY = 4, +}; + +u32 nx_hdmi_get_reg(u32 module_index, u32 offset); +void nx_hdmi_set_reg(u32 module_index, u32 offset, u32 regvalue); + +void nx_hdmi_set_base_address(u32 module_index, void *base_address); +void *nx_hdmi_get_base_address(u32 module_index); +u32 nx_hdmi_get_physical_address(u32 module_index); + +#endif diff --git a/drivers/video/nexell/soc/s5pxx18_soc_lvds.c b/drivers/video/nexell/soc/s5pxx18_soc_lvds.c new file mode 100644 index 0000000000..18c101bda7 --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_lvds.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#include <linux/types.h> +#include <linux/io.h> + +#include "s5pxx18_soc_disptop.h" +#include "s5pxx18_soc_lvds.h" + +#ifndef pow +static inline unsigned int pow(int a, int b) +{ + if (b == 0) + return 1; + else + return a * pow(a, b - 1); +} +#endif + +static struct nx_lvds_register_set *__g_pregister[NUMBER_OF_LVDS_MODULE]; + +int nx_lvds_initialize(void) +{ + static int binit; + u32 i; + + if (binit == 0) { + for (i = 0; i < NUMBER_OF_LVDS_MODULE; i++) + __g_pregister[i] = NULL; + binit = 1; + } + + return 1; +} + +u32 nx_lvds_get_number_of_module(void) +{ + return NUMBER_OF_LVDS_MODULE; +} + +u32 nx_lvds_get_size_of_register_set(void) +{ + return sizeof(struct nx_lvds_register_set); +} + +void nx_lvds_set_base_address(u32 module_index, void *base_address) +{ + __g_pregister[module_index] = + (struct nx_lvds_register_set *)base_address; +} + +void *nx_lvds_get_base_address(u32 module_index) +{ + return (void *)__g_pregister[module_index]; +} + +u32 nx_lvds_get_physical_address(u32 module_index) +{ + const u32 physical_addr[] = PHY_BASEADDR_LVDS_LIST; + + return physical_addr[module_index]; +} + +int nx_lvds_open_module(u32 module_index) +{ + return true; +} + +int nx_lvds_close_module(u32 module_index) +{ + return true; +} + +int nx_lvds_check_busy(u32 module_index) +{ + return false; +} + +void nx_lvds_set_lvdsctrl0(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdsctrl0); +} + +void nx_lvds_set_lvdsctrl1(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdsctrl1); +} + +void nx_lvds_set_lvdsctrl2(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdsctrl2); +} + +void nx_lvds_set_lvdsctrl3(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdsctrl3); +} + +void nx_lvds_set_lvdsctrl4(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdsctrl4); +} + +void nx_lvds_set_lvdstmode0(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdstmode0); +} + +void nx_lvds_set_lvdsloc0(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdsloc0); +} + +void nx_lvds_set_lvdsloc1(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdsloc1); +} + +void nx_lvds_set_lvdsloc2(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdsloc2); +} + +void nx_lvds_set_lvdsloc3(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdsloc3); +} + +void nx_lvds_set_lvdsloc4(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdsloc4); +} + +void nx_lvds_set_lvdsloc5(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdsloc5); +} + +void nx_lvds_set_lvdsloc6(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdsloc6); +} + +void nx_lvds_set_lvdslocmask0(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdslocmask0); +} + +void nx_lvds_set_lvdslocmask1(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdslocmask1); +} + +void nx_lvds_set_lvdslocpol0(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdslocpol0); +} + +void nx_lvds_set_lvdslocpol1(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(regvalue, &pregister->lvdslocpol1); +} + +void nx_lvds_set_lvdsdummy(u32 module_index, u32 regvalue) +{ + register struct nx_lvds_register_set *pregister; + u32 oldvalue; + + pregister = __g_pregister[module_index]; + oldvalue = readl(&pregister->lvdsctrl1) & 0x00ffffff; + writel(oldvalue | ((regvalue & 0xff) << 24), &pregister->lvdsctrl1); +} + +u32 nx_lvds_get_lvdsdummy(u32 module_index) +{ + register struct nx_lvds_register_set *pregister; + u32 oldvalue; + + pregister = __g_pregister[module_index]; + oldvalue = readl(&pregister->lvdsctrl1); + oldvalue = oldvalue >> 24; + return oldvalue; +} + +u32 nx_lvds_get_lvdsctrl0(u32 module_index) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + return (u32)readl(&pregister->lvdsctrl0); +} + +u32 nx_lvds_get_lvdsctrl1(u32 module_index) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + return (u32)readl(&pregister->lvdsctrl1); +} + +u32 nx_lvds_get_lvdsctrl2(u32 module_index) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + return (u32)readl(&pregister->lvdsctrl2); +} + +u32 nx_lvds_get_lvdsctrl3(u32 module_index) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + return (u32)readl(&pregister->lvdsctrl3); +} + +u32 nx_lvds_get_lvdsctrl4(u32 module_index) +{ + register struct nx_lvds_register_set *pregister; + + pregister = __g_pregister[module_index]; + return (u32)readl(&pregister->lvdsctrl4); +} diff --git a/drivers/video/nexell/soc/s5pxx18_soc_lvds.h b/drivers/video/nexell/soc/s5pxx18_soc_lvds.h new file mode 100644 index 0000000000..08f8e5c406 --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_lvds.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#ifndef _S5PXX18_SOC_LVDS_H_ +#define _S5PXX18_SOC_LVDS_H_ + +/* + * refter to s5pxx18_soc_disptop.h + * + * #define NUMBER_OF_LVDS_MODULE 1 + * #define PHY_BASEADDR_LVDS_MODULE 0xC010A000 + */ +#define PHY_BASEADDR_LVDS_LIST \ + { PHY_BASEADDR_LVDS_MODULE } + +struct nx_lvds_register_set { + u32 lvdsctrl0; + u32 lvdsctrl1; + u32 lvdsctrl2; + u32 lvdsctrl3; + u32 lvdsctrl4; + u32 _reserved0[3]; + u32 lvdsloc0; + u32 lvdsloc1; + u32 lvdsloc2; + u32 lvdsloc3; + u32 lvdsloc4; + u32 lvdsloc5; + u32 lvdsloc6; + u32 _reserved1; + u32 lvdslocmask0; + u32 lvdslocmask1; + u32 lvdslocpol0; + u32 lvdslocpol1; + u32 lvdstmode0; + u32 lvdstmode1; + u32 _reserved2[2]; +}; + +int nx_lvds_initialize(void); +u32 nx_lvds_get_number_of_module(void); +u32 nx_lvds_get_size_of_register_set(void); +void nx_lvds_set_base_address(u32 module_index, void *base_address); +void *nx_lvds_get_base_address(u32 module_index); +u32 nx_lvds_get_physical_address(u32 module_index); +int nx_lvds_open_module(u32 module_index); +int nx_lvds_close_module(u32 module_index); +int nx_lvds_check_busy(u32 module_index); + +void nx_lvds_set_lvdsctrl0(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdsctrl1(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdsctrl2(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdsctrl3(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdsctrl4(u32 module_index, u32 regvalue); +u32 nx_lvds_get_lvdsctrl0(u32 module_index); +u32 nx_lvds_get_lvdsctrl1(u32 module_index); +u32 nx_lvds_get_lvdsctrl2(u32 module_index); +u32 nx_lvds_get_lvdsctrl3(u32 module_index); +u32 nx_lvds_get_lvdsctrl4(u32 module_index); + +void nx_lvds_set_lvdstmode0(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdsloc0(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdsloc1(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdsloc2(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdsloc3(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdsloc4(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdsloc5(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdsloc6(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdslocmask0(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdslocmask1(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdslocpol0(u32 module_index, u32 regvalue); +void nx_lvds_set_lvdslocpol1(u32 module_index, u32 regvalue); + +void nx_lvds_set_lvdslocpol1(u32 module_index, u32 regvalue); + +void nx_lvds_set_lvdsdummy(u32 module_index, u32 regvalue); +u32 nx_lvds_get_lvdsdummy(u32 module_index); + +#endif diff --git a/drivers/video/nexell/soc/s5pxx18_soc_mipi.c b/drivers/video/nexell/soc/s5pxx18_soc_mipi.c new file mode 100644 index 0000000000..1000ddb642 --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_mipi.c @@ -0,0 +1,580 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#include <linux/types.h> +#include <linux/io.h> + +#include "s5pxx18_soc_disptop.h" +#include "s5pxx18_soc_mipi.h" + +static struct nx_mipi_register_set *__g_pregister[NUMBER_OF_MIPI_MODULE]; + +int nx_mipi_smoke_test(u32 module_index) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + + if (pregister->csis_config_ch0 != 0x000000FC) + return false; + + if (pregister->dsim_intmsk != 0xB337FFFF) + return false; + + writel(0xDEADC0DE, &pregister->csis_dphyctrl); + writel(0xFFFFFFFF, &pregister->csis_ctrl2); + writel(0xDEADC0DE, &pregister->dsim_msync); + + if (pregister->csis_dphyctrl != 0xDE80001E) + return false; + + if ((pregister->csis_ctrl2 & (~1)) != 0xEEE00010) + return false; + + if (pregister->dsim_msync != 0xDE80C0DE) + return false; + + return true; +} + +void nx_mipi_set_base_address(u32 module_index, void *base_address) +{ + __g_pregister[module_index] = + (struct nx_mipi_register_set *)base_address; +} + +void *nx_mipi_get_base_address(u32 module_index) +{ + return (void *)__g_pregister[module_index]; +} + +u32 nx_mipi_get_physical_address(u32 module_index) +{ + const u32 physical_addr[] = PHY_BASEADDR_MIPI_LIST; + + return physical_addr[module_index]; +} + +#define __nx_mipi_valid_dsi_intmask__ \ + (~((1 << 26) | (1 << 23) | (1 << 22) | (1 << 19))) + +void nx_mipi_set_interrupt_enable(u32 module_index, u32 int_num, int enable) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + + pregister = __g_pregister[module_index]; + if (int_num < 32) { + regvalue = pregister->csis_intmsk; + regvalue &= ~(1ul << int_num); + regvalue |= (u32)enable << int_num; + writel(regvalue, &pregister->csis_intmsk); + } else { + regvalue = pregister->dsim_intmsk; + regvalue &= ~(1ul << (int_num - 32)); + regvalue |= (u32)enable << (int_num - 32); + writel(regvalue, &pregister->dsim_intmsk); + } +} + +int nx_mipi_get_interrupt_enable(u32 module_index, u32 int_num) +{ + if (int_num < 32) + return (int)((__g_pregister[module_index]->csis_intmsk >> + int_num) & 0x01); + else + return (int)((__g_pregister[module_index]->dsim_intmsk >> + (int_num - 32)) & 0x01); +} + +int nx_mipi_get_interrupt_pending(u32 module_index, u32 int_num) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + int ret; + + pregister = __g_pregister[module_index]; + if (int_num < 32) { + regvalue = pregister->csis_intmsk; + regvalue &= pregister->csis_intsrc; + ret = (int)((regvalue >> int_num) & 0x01); + } else { + regvalue = pregister->dsim_intmsk; + regvalue &= pregister->dsim_intsrc; + ret = (int)((regvalue >> (int_num - 32)) & 0x01); + } + + return ret; +} + +void nx_mipi_clear_interrupt_pending(u32 module_index, u32 int_num) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + if (int_num < 32) + writel(1ul << int_num, &pregister->csis_intsrc); + else + writel(1ul << (int_num - 32), &pregister->dsim_intsrc); +} + +void nx_mipi_set_interrupt_enable_all(u32 module_index, int enable) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + if (enable) + writel(__nx_mipi_valid_dsi_intmask__, &pregister->dsim_intmsk); + else + writel(0, &pregister->dsim_intmsk); +} + +int nx_mipi_get_interrupt_enable_all(u32 module_index) +{ + if (__g_pregister[module_index]->csis_intmsk) + return true; + + if (__g_pregister[module_index]->dsim_intmsk) + return true; + + return false; +} + +int nx_mipi_get_interrupt_pending_all(u32 module_index) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + + pregister = __g_pregister[module_index]; + regvalue = pregister->csis_intmsk; + regvalue &= pregister->csis_intsrc; + + if (regvalue) + return true; + + regvalue = pregister->dsim_intmsk; + regvalue &= pregister->dsim_intsrc; + + if (regvalue) + return true; + + return false; +} + +void nx_mipi_clear_interrupt_pending_all(u32 module_index) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(__nx_mipi_valid_dsi_intmask__, &pregister->dsim_intsrc); +} + +int32_t nx_mipi_get_interrupt_pending_number(u32 module_index) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + int i; + + pregister = __g_pregister[module_index]; + regvalue = pregister->csis_intmsk; + regvalue &= pregister->csis_intsrc; + if (regvalue != 0) { + for (i = 0; i < 32; i++) { + if (regvalue & 1ul) + return i; + regvalue >>= 1; + } + } + + regvalue = pregister->dsim_intmsk; + regvalue &= pregister->dsim_intsrc; + if (regvalue != 0) { + for (i = 0; i < 32; i++) { + if (regvalue & 1ul) + return i + 32; + regvalue >>= 1; + } + } + return -1; +} + +#define writereg(regname, mask, value) \ + regvalue = pregister->(regname); \ + regvalue = (regvalue & (~(mask))) | (value); \ + writel(regvalue, &pregister->(regname)) + +void nx_mipi_dsi_get_status(u32 module_index, u32 *pulps, u32 *pstop, + u32 *pispllstable, u32 *pisinreset, + u32 *pisbackward, u32 *pishsclockready) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + + pregister = __g_pregister[module_index]; + regvalue = pregister->dsim_status; + if (pulps) { + *pulps = 0; + if (regvalue & (1 << 4)) + *pulps |= (1 << 0); + if (regvalue & (1 << 5)) + *pulps |= (1 << 1); + if (regvalue & (1 << 6)) + *pulps |= (1 << 2); + if (regvalue & (1 << 7)) + *pulps |= (1 << 3); + if (regvalue & (1 << 9)) + *pulps |= (1 << 4); + } + + if (pstop) { + *pstop = 0; + if (regvalue & (1 << 0)) + *pstop |= (1 << 0); + if (regvalue & (1 << 1)) + *pstop |= (1 << 1); + if (regvalue & (1 << 2)) + *pstop |= (1 << 2); + if (regvalue & (1 << 3)) + *pstop |= (1 << 3); + if (regvalue & (1 << 8)) + *pstop |= (1 << 4); + } + + if (pispllstable) + *pispllstable = (regvalue >> 31) & 1; + + if (pisinreset) + *pisinreset = ((regvalue >> 20) & 1) ? 0 : 1; + + if (pisbackward) + *pisbackward = (regvalue >> 16) & 1; + + if (pishsclockready) + *pishsclockready = (regvalue >> 10) & 1; +} + +void nx_mipi_dsi_software_reset(u32 module_index) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + + writel(0x00010001, &pregister->dsim_swrst); + + while (0 != (readl(&pregister->dsim_status) & (1 << 20))) + ; + + writel(0x00000000, &pregister->dsim_swrst); +} + +void nx_mipi_dsi_set_clock(u32 module_index, int enable_txhsclock, + int use_external_clock, int enable_byte_clock, + int enable_escclock_clock_lane, + int enable_escclock_data_lane0, + int enable_escclock_data_lane1, + int enable_escclock_data_lane2, + int enable_escclock_data_lane3, + int enable_escprescaler, u32 escprescalervalue) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + + pregister = __g_pregister[module_index]; + regvalue = 0; + regvalue |= (enable_txhsclock << 31); + regvalue |= (use_external_clock << 27); + regvalue |= (enable_byte_clock << 24); + regvalue |= (enable_escclock_clock_lane << 19); + regvalue |= (enable_escclock_data_lane0 << 20); + regvalue |= (enable_escclock_data_lane1 << 21); + regvalue |= (enable_escclock_data_lane2 << 22); + regvalue |= (enable_escclock_data_lane3 << 23); + regvalue |= (enable_escprescaler << 28); + regvalue |= escprescalervalue; + + writel(regvalue, &pregister->dsim_clkctrl); +} + +void nx_mipi_dsi_set_timeout(u32 module_index, u32 bta_tout, u32 lpdrtout) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + + pregister = __g_pregister[module_index]; + regvalue = 0; + regvalue |= (bta_tout << 16); + regvalue |= (lpdrtout << 0); + + writel(regvalue, &pregister->dsim_timeout); +} + +void nx_mipi_dsi_set_config_video_mode(u32 module_index, + int enable_auto_flush_main_display_fifo, + int enable_auto_vertical_count, + int enable_burst, + enum nx_mipi_dsi_syncmode sync_mode, + int enable_eo_tpacket, + int enable_hsync_end_packet, + int enable_hfp, int enable_hbp, + int enable_hsa, + u32 number_of_virtual_channel, + enum nx_mipi_dsi_format format, + u32 number_of_words_in_hfp, + u32 number_of_words_in_hbp, + u32 number_of_words_in_hsync, + u32 number_of_lines_in_vfp, + u32 number_of_lines_in_vbp, + u32 number_of_lines_in_vsync, + u32 number_of_lines_in_command_allow) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue; + + pregister = __g_pregister[module_index]; + newvalue = (1 << 25); + newvalue |= ((1 - enable_auto_flush_main_display_fifo) << 29); + newvalue |= (enable_auto_vertical_count << 24); + newvalue |= (enable_burst << 26); + newvalue |= (sync_mode << 27); + newvalue |= ((1 - enable_eo_tpacket) << 28); + newvalue |= (enable_hsync_end_packet << 23); + newvalue |= ((1 - enable_hfp) << 22); + newvalue |= ((1 - enable_hbp) << 21); + newvalue |= ((1 - enable_hsa) << 20); + newvalue |= (number_of_virtual_channel << 18); + newvalue |= (format << 12); + + writereg(dsim_config, 0xFFFFFF00, newvalue); + + newvalue = (number_of_lines_in_command_allow << 28); + newvalue |= (number_of_lines_in_vfp << 16); + newvalue |= (number_of_lines_in_vbp << 0); + + writel(newvalue, &pregister->dsim_mvporch); + + newvalue = (number_of_words_in_hfp << 16); + newvalue |= (number_of_words_in_hbp << 0); + + writel(newvalue, &pregister->dsim_mhporch); + + newvalue = (number_of_words_in_hsync << 0); + newvalue |= (number_of_lines_in_vsync << 22); + + writel(newvalue, &pregister->dsim_msync); +} + +void nx_mipi_dsi_set_config_command_mode(u32 module_index, + int + enable_auto_flush_main_display_fifo, + int enable_eo_tpacket, + u32 number_of_virtual_channel, + enum nx_mipi_dsi_format format) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue; + + pregister = __g_pregister[module_index]; + newvalue = (0 << 25); + newvalue |= (enable_auto_flush_main_display_fifo << 29); + newvalue |= (enable_eo_tpacket << 28); + newvalue |= (number_of_virtual_channel << 18); + newvalue |= (format << 12); + writereg(dsim_config, 0xFFFFFF00, newvalue); +} + +void nx_mipi_dsi_set_escape_mode(u32 module_index, u32 stop_state_count, + int force_stop_state, int force_bta, + enum nx_mipi_dsi_lpmode cmdin_lp, + enum nx_mipi_dsi_lpmode txinlp) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue; + + pregister = __g_pregister[module_index]; + newvalue = (stop_state_count << 21); + newvalue |= (force_stop_state << 20); + newvalue |= (force_bta << 16); + newvalue |= (cmdin_lp << 7); + newvalue |= (txinlp << 6); + writereg(dsim_escmode, 0xFFFFFFC0, newvalue); +} + +void nx_mipi_dsi_set_escape_lp(u32 module_index, + enum nx_mipi_dsi_lpmode cmdin_lp, + enum nx_mipi_dsi_lpmode txinlp) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue = 0; + + pregister = __g_pregister[module_index]; + newvalue |= (cmdin_lp << 7); + newvalue |= (txinlp << 6); + writereg(dsim_escmode, 0xC0, newvalue); +} + +void nx_mipi_dsi_remote_reset_trigger(u32 module_index) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue; + + pregister = __g_pregister[module_index]; + newvalue = (1 << 4); + writereg(dsim_escmode, (1 << 4), newvalue); + + while (readl(&pregister->dsim_escmode) & (1 << 4)) + ; +} + +void nx_mipi_dsi_set_ulps(u32 module_index, int ulpsclocklane, int ulpsdatalane) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + + pregister = __g_pregister[module_index]; + regvalue = pregister->dsim_escmode; + + if (ulpsclocklane) { + regvalue &= ~(1 << 0); + regvalue |= (1 << 1); + } else { + regvalue |= (1 << 0); + } + + if (ulpsdatalane) { + regvalue &= ~(1 << 2); + regvalue |= (1 << 3); + } else { + regvalue |= (1 << 2); + } + + writel(regvalue, &pregister->dsim_escmode); + + if (ulpsclocklane) + while ((1 << 9) == + (readl(&pregister->dsim_status) & (1 << 9))) + ; + else + while (0 != (readl(&pregister->dsim_status) & (1 << 9))) + ; + + if (ulpsdatalane) + while ((15 << 4) == + (readl(&pregister->dsim_status) & (15 << 4))) + ; + else + while (0 != (readl(&pregister->dsim_status) & (15 << 4))) + ; + + if (!ulpsclocklane) + regvalue &= (3 << 0); + + if (!ulpsdatalane) + regvalue |= (3 << 2); + + writel(regvalue, &pregister->dsim_escmode); +} + +void nx_mipi_dsi_set_size(u32 module_index, u32 width, u32 height) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue; + + pregister = __g_pregister[module_index]; + newvalue = (height << 16); + newvalue |= (width << 0); + writereg(dsim_mdresol, 0x0FFFFFFF, newvalue); +} + +void nx_mipi_dsi_set_enable(u32 module_index, int enable) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + + pregister = __g_pregister[module_index]; + writereg(dsim_mdresol, (1 << 31), (enable << 31)); +} + +void nx_mipi_dsi_set_phy(u32 module_index, u32 number_of_data_lanes, + int enable_clock_lane, int enable_data_lane0, + int enable_data_lane1, int enable_data_lane2, + int enable_data_lane3, int swap_clock_lane, + int swap_data_lane) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue; + + pregister = __g_pregister[module_index]; + newvalue = (number_of_data_lanes << 5); + newvalue |= (enable_clock_lane << 0); + newvalue |= (enable_data_lane0 << 1); + newvalue |= (enable_data_lane1 << 2); + newvalue |= (enable_data_lane2 << 3); + newvalue |= (enable_data_lane3 << 4); + writereg(dsim_config, 0xFF, newvalue); + newvalue = (swap_clock_lane << 1); + newvalue |= (swap_data_lane << 0); + writereg(dsim_phyacchr1, 0x3, newvalue); +} + +void nx_mipi_dsi_set_pll(u32 module_index, int enable, u32 pllstabletimer, + u32 m_pllpms, u32 m_bandctl, u32 m_dphyctl, + u32 b_dphyctl) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue; + + pregister = __g_pregister[module_index]; + if (!enable) { + newvalue = (enable << 23); + newvalue |= (m_pllpms << 1); + newvalue |= (m_bandctl << 24); + writereg(dsim_pllctrl, 0x0FFFFFFF, newvalue); + } + + writel(m_dphyctl, &pregister->dsim_phyacchr); + writel(pllstabletimer, &pregister->dsim_plltmr); + writel((b_dphyctl << 9), &pregister->dsim_phyacchr1); + + if (enable) { + newvalue = (enable << 23); + newvalue |= (m_pllpms << 1); + newvalue |= (m_bandctl << 24); + writereg(dsim_pllctrl, 0x0FFFFFFF, newvalue); + } +} + +void nx_mipi_dsi_write_pkheader(u32 module_index, u32 data) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(data, &pregister->dsim_pkthdr); +} + +void nx_mipi_dsi_write_payload(u32 module_index, u32 data) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(data, &pregister->dsim_payload); +} + +u32 nx_mipi_dsi_read_fifo_status(u32 module_index) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + return readl(&pregister->dsim_fifoctrl); +} diff --git a/drivers/video/nexell/soc/s5pxx18_soc_mipi.h b/drivers/video/nexell/soc/s5pxx18_soc_mipi.h new file mode 100644 index 0000000000..63751ca83f --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_mipi.h @@ -0,0 +1,291 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#ifndef _S5PXX18_SOC_MIPI_H_ +#define _S5PXX18_SOC_MIPI_H_ + +#define NUMBER_OF_MIPI_MODULE 1 +#define PHY_BASEADDR_MIPI_MODULE 0xC00D0000 +#define PHY_BASEADDR_MIPI_LIST \ + { PHY_BASEADDR_MIPI_MODULE } + +#define nx_mipi_numberof_csi_channels 2 + +struct nx_mipi_register_set { + u32 csis_control; + u32 csis_dphyctrl; + u32 csis_config_ch0; + u32 csis_dphysts; + u32 csis_intmsk; + u32 csis_intsrc; + u32 csis_ctrl2; + u32 csis_version; + u32 csis_dphyctrl_0; + u32 csis_dphyctrl_1; + u32 __reserved0; + u32 csis_resol_ch0; + u32 __reserved1; + u32 __reserved2; + u32 sdw_config_ch0; + u32 sdw_resol_ch0; + u32 csis_config_ch1; + u32 csis_resol_ch1; + u32 sdw_config_ch1; + u32 sdw_resol_ch1; + u32 csis_config_ch2; + u32 csis_resol_ch2; + u32 sdw_config_ch2; + u32 sdw_resol_ch2; + u32 csis_config_ch3; + u32 csis_resol_ch3; + u32 sdw_config_ch3; + u32 sdw_resol_3; + u32 __reserved3[(16 + 128) / 4]; + + u32 dsim_status; + u32 dsim_swrst; + u32 dsim_clkctrl; + u32 dsim_timeout; + u32 dsim_config; + u32 dsim_escmode; + u32 dsim_mdresol; + u32 dsim_mvporch; + u32 dsim_mhporch; + u32 dsim_msync; + u32 dsim_sdresol; + u32 dsim_intsrc; + u32 dsim_intmsk; + u32 dsim_pkthdr; + u32 dsim_payload; + u32 dsim_rxfifo; + u32 dsim_fifothld; + u32 dsim_fifoctrl; + u32 dsim_memacchr; + u32 dsim_pllctrl; + u32 dsim_plltmr; + u32 dsim_phyacchr; + u32 dsim_phyacchr1; + + u32 __reserved4[(0x2000 - 0x015C) / 4]; + u32 mipi_csis_pktdata[0x2000 / 4]; +}; + +enum nx_mipi_dsi_syncmode { + nx_mipi_dsi_syncmode_event = 0, + nx_mipi_dsi_syncmode_pulse = 1, +}; + +enum nx_mipi_dsi_format { + nx_mipi_dsi_format_command3 = 0, + nx_mipi_dsi_format_command8 = 1, + nx_mipi_dsi_format_command12 = 2, + nx_mipi_dsi_format_command16 = 3, + nx_mipi_dsi_format_rgb565 = 4, + nx_mipi_dsi_format_rgb666_packed = 5, + nx_mipi_dsi_format_rgb666 = 6, + nx_mipi_dsi_format_rgb888 = 7 +}; + +enum nx_mipi_dsi_lpmode { + nx_mipi_dsi_lpmode_hs = 0, + nx_mipi_dsi_lpmode_lp = 1 +}; + +enum nx_mipi_phy_b_dphyctl { + nx_mipi_phy_b_dphyctl_m_txclkesc_20_mhz = 0x1F4, + nx_mipi_phy_b_dphyctl_m_txclkesc_19_mhz = 0x1DB, + nx_mipi_phy_b_dphyctl_m_txclkesc_18_mhz = 0x1C2, + nx_mipi_phy_b_dphyctl_m_txclkesc_17_mhz = 0x1A9, + nx_mipi_phy_b_dphyctl_m_txclkesc_16_mhz = 0x190, + nx_mipi_phy_b_dphyctl_m_txclkesc_15_mhz = 0x177, + nx_mipi_phy_b_dphyctl_m_txclkesc_14_mhz = 0x15E, + nx_mipi_phy_b_dphyctl_m_txclkesc_13_mhz = 0x145, + nx_mipi_phy_b_dphyctl_m_txclkesc_12_mhz = 0x12C, + nx_mipi_phy_b_dphyctl_m_txclkesc_11_mhz = 0x113, + nx_mipi_phy_b_dphyctl_m_txclkesc_10_mhz = 0x0FA, + nx_mipi_phy_b_dphyctl_m_txclkesc_9_mhz = 0x0E1, + nx_mipi_phy_b_dphyctl_m_txclkesc_8_mhz = 0x0C8, + nx_mipi_phy_b_dphyctl_m_txclkesc_7_mhz = 0x0AF, + nx_mipi_phy_b_dphyctl_m_txclkesc_6_mhz = 0x096, + nx_mipi_phy_b_dphyctl_m_txclkesc_5_mhz = 0x07D, + nx_mipi_phy_b_dphyctl_m_txclkesc_4_mhz = 0x064, + nx_mipi_phy_b_dphyctl_m_txclkesc_3_mhz = 0x04B, + nx_mipi_phy_b_dphyctl_m_txclkesc_2_mhz = 0x032, + nx_mipi_phy_b_dphyctl_m_txclkesc_1_mhz = 0x019, + nx_mipi_phy_b_dphyctl_m_txclkesc_0_10_mhz = 0x003, + nx_mipi_phy_b_dphyctl_m_txclkesc_0_01_mhz = 0x000 +}; + +enum { + nx_mipi_rst = 0, + nx_mipi_rst_dsi_i, + nx_mipi_rst_csi_i, + nx_mipi_rst_phy_s, + nx_mipi_rst_phy_m +}; + +enum nx_mipi_int { + nx_mipi_int_csi_even_before = 31, + nx_mipi_int_csi_even_after = 30, + nx_mipi_int_csi_odd_before = 29, + nx_mipi_int_csi_odd_after = 28, + nx_mipi_int_csi_frame_start_ch3 = 27, + nx_mipi_int_csi_frame_start_ch2 = 26, + nx_mipi_int_csi_frame_start_ch1 = 25, + nx_mipi_int_csi_frame_start_ch0 = 24, + nx_mipi_int_csi_frame_end_ch3 = 23, + nx_mipi_int_csi_frame_end_ch2 = 22, + nx_mipi_int_csi_frame_end_ch1 = 21, + nx_mipi_int_csi_frame_end_ch0 = 20, + nx_mipi_int_csi_err_sot_hs_ch3 = 19, + nx_mipi_int_csi_err_sot_hs_ch2 = 18, + nx_mipi_int_csi_err_sot_hs_ch1 = 17, + nx_mipi_int_csi_err_sot_hs_ch0 = 16, + nx_mipi_int_csi_err_lost_fs_ch3 = 15, + nx_mipi_int_csi_err_lost_fs_ch2 = 14, + nx_mipi_int_csi_err_lost_fs_ch1 = 13, + nx_mipi_int_csi_err_lost_fs_ch0 = 12, + nx_mipi_int_csi_err_lost_fe_ch3 = 11, + nx_mipi_int_csi_err_lost_fe_ch2 = 10, + nx_mipi_int_csi_err_lost_fe_ch1 = 9, + nx_mipi_int_csi_err_lost_fe_ch0 = 8, + nx_mipi_int_csi_err_over_ch3 = 7, + nx_mipi_int_csi_err_over_ch2 = 6, + nx_mipi_int_csi_err_over_ch1 = 5, + nx_mipi_int_csi_err_over_ch0 = 4, + + nx_mipi_int_csi_err_ecc = 2, + nx_mipi_int_csi_err_crc = 1, + nx_mipi_int_csi_err_id = 0, + nx_mipi_int_dsi_pll_stable = 32 + 31, + nx_mipi_int_dsi_sw_rst_release = 32 + 30, + nx_mipi_int_dsi_sfrplfifoempty = 32 + 29, + nx_mipi_int_dsi_sfrphfifoempty = 32 + 28, + nx_mipi_int_dsi_sync_override = 32 + 27, + + nx_mipi_int_dsi_bus_turn_over = 32 + 25, + nx_mipi_int_dsi_frame_done = 32 + 24, + + nx_mipi_int_dsi_lpdr_tout = 32 + 21, + nx_mipi_int_dsi_ta_tout = 32 + 20, + + nx_mipi_int_dsi_rx_dat_done = 32 + 18, + nx_mipi_int_dsi_rx_te = 32 + 17, + nx_mipi_int_dsi_rx_ack = 32 + 16, + nx_mipi_int_dsi_err_rx_ecc = 32 + 15, + nx_mipi_int_dsi_err_rx_crc = 32 + 14, + nx_mipi_int_dsi_err_esc3 = 32 + 13, + nx_mipi_int_dsi_err_esc2 = 32 + 12, + nx_mipi_int_dsi_err_esc1 = 32 + 11, + nx_mipi_int_dsi_err_esc0 = 32 + 10, + nx_mipi_int_dsi_err_sync3 = 32 + 9, + nx_mipi_int_dsi_err_sync2 = 32 + 8, + nx_mipi_int_dsi_err_sync1 = 32 + 7, + nx_mipi_int_dsi_err_sync0 = 32 + 6, + nx_mipi_int_dsi_err_control3 = 32 + 5, + nx_mipi_int_dsi_err_control2 = 32 + 4, + nx_mipi_int_dsi_err_control1 = 32 + 3, + nx_mipi_int_dsi_err_control0 = 32 + 2, + nx_mipi_int_dsi_err_content_lp0 = 32 + 1, + nx_mipi_int_dsi_err_content_lp1 = 32 + 0, +}; + +#define DSI_TX_FIFO_SIZE 2048 +#define DSI_RX_FIFO_SIZE 256 +#define DSI_RX_FIFO_EMPTY 0x30800002 + +void nx_mipi_dsi_get_status(u32 module_index, u32 *pulps, u32 *pstop, + u32 *pispllstable, u32 *pisinreset, + u32 *pisbackward, u32 *pishsclockready); + +void nx_mipi_dsi_software_reset(u32 module_index); + +void nx_mipi_dsi_set_clock(u32 module_index, int enable_txhsclock, + int use_external_clock, int enable_byte_clock, + int enable_escclock_clock_lane, + int enable_escclock_data_lane0, + int enable_escclock_data_lane1, + int enable_escclock_data_lane2, + int enable_escclock_data_lane3, + int enable_escprescaler, + u32 escprescalervalue); + +void nx_mipi_dsi_set_timeout(u32 module_index, u32 bta_tout, + u32 lpdrtout); + +void nx_mipi_dsi_set_config_video_mode(u32 module_index, + int enable_auto_flush_main_display_fifo, + int enable_auto_vertical_count, + int enable_burst, + enum nx_mipi_dsi_syncmode + sync_mode, int enable_eo_tpacket, + int enable_hsync_end_packet, + int enable_hfp, int enable_hbp, + int enable_hsa, + u32 number_of_virtual_channel, + enum nx_mipi_dsi_format format, + u32 number_of_words_in_hfp, + u32 number_of_words_in_hbp, + u32 number_of_words_in_hsync, + u32 number_of_lines_in_vfp, + u32 number_of_lines_in_vbp, + u32 number_of_lines_in_vsync, + u32 number_of_lines_in_command_allow); + +void nx_mipi_dsi_set_config_command_mode(u32 module_index, + int enable_auto_flush_main_display_fifo, + int enable_eo_tpacket, + u32 number_of_virtual_channel, + enum nx_mipi_dsi_format format); + +void nx_mipi_dsi_set_escape_mode(u32 module_index, u32 stop_state_count, + int force_stop_state, int force_bta, + enum nx_mipi_dsi_lpmode cmdin_lp, + enum nx_mipi_dsi_lpmode txinlp); +void nx_mipi_dsi_set_escape_lp(u32 module_index, + enum nx_mipi_dsi_lpmode cmdin_lp, + enum nx_mipi_dsi_lpmode txinlp); + +void nx_mipi_dsi_remote_reset_trigger(u32 module_index); +void nx_mipi_dsi_set_ulps(u32 module_index, int ulpsclocklane, + int ulpsdatalane); +void nx_mipi_dsi_set_size(u32 module_index, u32 width, u32 height); +void nx_mipi_dsi_set_enable(u32 module_index, int enable); +void nx_mipi_dsi_set_phy(u32 module_index, u32 number_of_data_lanes, + int enable_clock_lane, int enable_data_lane0, + int enable_data_lane1, int enable_data_lane2, + int enable_data_lane3, int swap_clock_lane, + int swap_data_lane); + +void nx_mipi_dsi_set_pll(u32 module_index, int enable, + u32 pllstabletimer, u32 m_pllpms, u32 m_bandctl, + u32 m_dphyctl, u32 b_dphyctl); + +void nx_mipi_dsi_write_pkheader(u32 module_index, u32 data); +void nx_mipi_dsi_write_payload(u32 module_index, u32 data); +u32 nx_mipi_dsi_read_fifo(u32 module_index); +u32 nx_mipi_dsi_read_fifo_status(u32 module_index); + +int nx_mipi_smoke_test(u32 module_index); +void nx_mipi_set_base_address(u32 module_index, void *base_address); +void *nx_mipi_get_base_address(u32 module_index); +u32 nx_mipi_get_physical_address(u32 module_index); + +void nx_mipi_dsi_set_interrupt_enable_all(u32 module_index, int enable); +void nx_mipi_dsi_set_interrupt_enable(u32 module_index, + u32 int_num, int enable); +int nx_mipi_dsi_get_interrupt_enable(u32 module_index, u32 int_num); +int nx_mipi_dsi_get_interrupt_enable_all(u32 module_index); + +int nx_mipi_dsi_get_interrupt_pending(u32 module_index, u32 int_num); +int nx_mipi_dsi_get_interrupt_pending_all(u32 module_index); +int32_t nx_mipi_dsi_get_interrupt_pending_number(u32 module_index); + +void nx_mipi_dsi_clear_interrupt_pending(u32 module_index, u32 int_num); +void nx_mipi_dsi_clear_interrupt_pending_all(u32 module_index); + +#endif diff --git a/drivers/video/nexell/soc/s5pxx18_soc_mlc.c b/drivers/video/nexell/soc/s5pxx18_soc_mlc.c new file mode 100644 index 0000000000..c8cf833f30 --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_mlc.c @@ -0,0 +1,1861 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#include <linux/types.h> +#include <linux/io.h> + +#include "s5pxx18_soc_mlc.h" + +static struct { + struct nx_mlc_register_set *pregister; +} __g_module_variables[NUMBER_OF_MLC_MODULE] = { { NULL, },}; + +int nx_mlc_initialize(void) +{ + static int binit; + u32 i; + + if (binit == 0) { + for (i = 0; i < NUMBER_OF_MLC_MODULE; i++) + __g_module_variables[i].pregister = NULL; + binit = 1; + } + return 1; +} + +u32 nx_mlc_get_physical_address(u32 module_index) +{ + const u32 physical_addr[] = PHY_BASEADDR_MLC_LIST; + + return physical_addr[module_index]; +} + +void nx_mlc_set_base_address(u32 module_index, void *base_address) +{ + __g_module_variables[module_index].pregister = + (struct nx_mlc_register_set *)base_address; +} + +void *nx_mlc_get_base_address(u32 module_index) +{ + return (void *)__g_module_variables[module_index].pregister; +} + +void nx_mlc_set_clock_pclk_mode(u32 module_index, enum nx_pclkmode mode) +{ + const u32 pclkmode_pos = 3; + u32 clkmode = 0; + + register u32 regvalue; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + switch (mode) { + case nx_pclkmode_dynamic: + clkmode = 0; + break; + case nx_pclkmode_always: + clkmode = 1; + break; + default: + break; + } + regvalue = pregister->mlcclkenb; + regvalue &= ~(1ul << pclkmode_pos); + regvalue |= (clkmode & 0x01) << pclkmode_pos; + + writel(regvalue, &pregister->mlcclkenb); +} + +enum nx_pclkmode nx_mlc_get_clock_pclk_mode(u32 module_index) +{ + const u32 pclkmode_pos = 3; + + if (__g_module_variables[module_index].pregister->mlcclkenb & + (1ul << pclkmode_pos)) { + return nx_pclkmode_always; + } + return nx_pclkmode_dynamic; +} + +void nx_mlc_set_clock_bclk_mode(u32 module_index, enum nx_bclkmode mode) +{ + register u32 regvalue; + register struct nx_mlc_register_set *pregister; + u32 clkmode = 0; + + pregister = __g_module_variables[module_index].pregister; + switch (mode) { + case nx_bclkmode_disable: + clkmode = 0; + break; + case nx_bclkmode_dynamic: + clkmode = 2; + break; + case nx_bclkmode_always: + clkmode = 3; + break; + default: + break; + } + regvalue = pregister->mlcclkenb; + regvalue &= ~(0x3); + regvalue |= clkmode & 0x3; + + writel(regvalue, &pregister->mlcclkenb); +} + +enum nx_bclkmode nx_mlc_get_clock_bclk_mode(u32 module_index) +{ + const u32 bclkmode = 3ul << 0; + + switch (__g_module_variables[module_index].pregister->mlcclkenb & + bclkmode) { + case 0: + return nx_bclkmode_disable; + case 2: + return nx_bclkmode_dynamic; + case 3: + return nx_bclkmode_always; + } + return nx_bclkmode_disable; +} + +void nx_mlc_set_top_power_mode(u32 module_index, int bpower) +{ + const u32 pixelbuffer_pwd_pos = 11; + const u32 pixelbuffer_pwd_mask = 1ul << pixelbuffer_pwd_pos; + const u32 dittyflag_mask = 1ul << 3; + register struct nx_mlc_register_set *pregister; + register u32 regvalue; + + pregister = __g_module_variables[module_index].pregister; + regvalue = pregister->mlccontrolt; + regvalue &= ~(pixelbuffer_pwd_mask | dittyflag_mask); + regvalue |= (bpower << pixelbuffer_pwd_pos); + + writel(regvalue, &pregister->mlccontrolt); +} + +int nx_mlc_get_top_power_mode(u32 module_index) +{ + const u32 pixelbuffer_pwd_pos = 11; + const u32 pixelbuffer_pwd_mask = 1ul << pixelbuffer_pwd_pos; + + return (int)((__g_module_variables[module_index].pregister->mlccontrolt + & pixelbuffer_pwd_mask) >> + pixelbuffer_pwd_pos); +} + +void nx_mlc_set_top_sleep_mode(u32 module_index, int bsleep) +{ + const u32 pixelbuffer_sld_pos = 10; + const u32 pixelbuffer_sld_mask = 1ul << pixelbuffer_sld_pos; + const u32 dittyflag_mask = 1ul << 3; + register struct nx_mlc_register_set *pregister; + register u32 regvalue; + + bsleep = (int)((u32)bsleep ^ 1); + pregister = __g_module_variables[module_index].pregister; + regvalue = pregister->mlccontrolt; + regvalue &= ~(pixelbuffer_sld_mask | dittyflag_mask); + regvalue |= (bsleep << pixelbuffer_sld_pos); + + writel(regvalue, &pregister->mlccontrolt); +} + +int nx_mlc_get_top_sleep_mode(u32 module_index) +{ + const u32 pixelbuffer_sld_pos = 11; + const u32 pixelbuffer_sld_mask = 1ul << pixelbuffer_sld_pos; + + return (int)(((__g_module_variables[module_index].pregister->mlccontrolt + & pixelbuffer_sld_mask) >> + pixelbuffer_sld_pos) ^ 0x01); +} + +void nx_mlc_set_top_dirty_flag(u32 module_index) +{ + const u32 dirtyflag = 1ul << 3; + register struct nx_mlc_register_set *pregister; + register u32 regvalue; + + pregister = __g_module_variables[module_index].pregister; + regvalue = pregister->mlccontrolt; + regvalue |= dirtyflag; + + writel(regvalue, &pregister->mlccontrolt); +} + +int nx_mlc_get_top_dirty_flag(u32 module_index) +{ + const u32 dirtyflag_pos = 3; + const u32 dirtyflag_mask = 1ul << dirtyflag_pos; + + return (int)((readl(&__g_module_variables[module_index] + .pregister->mlccontrolt) & + dirtyflag_mask) >> dirtyflag_pos); +} + +void nx_mlc_set_mlc_enable(u32 module_index, int benb) +{ + const u32 mlcenb_pos = 1; + const u32 mlcenb_mask = 1ul << mlcenb_pos; + const u32 dirtyflag_pos = 3; + const u32 dirtyflag_mask = 1ul << dirtyflag_pos; + register u32 regvalue; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + regvalue = pregister->mlccontrolt; + regvalue &= ~(mlcenb_mask | dirtyflag_mask); + regvalue |= (benb << mlcenb_pos); + + writel(regvalue, &pregister->mlccontrolt); +} + +int nx_mlc_get_mlc_enable(u32 module_index) +{ + const u32 mlcenb_pos = 1; + const u32 mlcenb_mask = 1ul << mlcenb_pos; + + return (int)((__g_module_variables[module_index].pregister->mlccontrolt + & mlcenb_mask) >> mlcenb_pos); +} + +void nx_mlc_set_field_enable(u32 module_index, int benb) +{ + const u32 fieldenb_pos = 0; + const u32 fieldenb_mask = 1ul << fieldenb_pos; + const u32 dirtyflag_pos = 3; + const u32 dirtyflag_mask = 1ul << dirtyflag_pos; + register u32 regvalue; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + regvalue = pregister->mlccontrolt; + regvalue &= ~(fieldenb_mask | dirtyflag_mask); + regvalue |= (benb << fieldenb_pos); + + writel(regvalue, &pregister->mlccontrolt); +} + +int nx_mlc_get_field_enable(u32 module_index) +{ + const u32 fieldenb_pos = 0; + const u32 fieldenb_mask = 1ul << fieldenb_pos; + + return (int)(__g_module_variables[module_index].pregister->mlccontrolt & + fieldenb_mask); +} + +void nx_mlc_set_layer_priority(u32 module_index, enum nx_mlc_priority priority) +{ + const u32 priority_pos = 8; + const u32 priority_mask = 0x03 << priority_pos; + const u32 dirtyflag_pos = 3; + const u32 dirtyflag_mask = 1ul << dirtyflag_pos; + register struct nx_mlc_register_set *pregister; + register u32 regvalue; + + pregister = __g_module_variables[module_index].pregister; + regvalue = pregister->mlccontrolt; + regvalue &= ~(priority_mask | dirtyflag_mask); + regvalue |= (priority << priority_pos); + + writel(regvalue, &pregister->mlccontrolt); +} + +void nx_mlc_set_screen_size(u32 module_index, u32 width, u32 height) +{ + register struct nx_mlc_register_set *pregister; + register u32 regvalue; + + pregister = __g_module_variables[module_index].pregister; + regvalue = ((height - 1) << 16) | (width - 1); + + writel(regvalue, &pregister->mlcscreensize); +} + +void nx_mlc_get_screen_size(u32 module_index, u32 *pwidth, u32 *pheight) +{ + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + if (pwidth) + *pwidth = (pregister->mlcscreensize & 0x0fff) + 1; + + if (pheight) + *pheight = ((pregister->mlcscreensize >> 16) & 0x0fff) + 1; +} + +void nx_mlc_set_background(u32 module_index, u32 color) +{ + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel(color, &pregister->mlcbgcolor); +} + +void nx_mlc_set_dirty_flag(u32 module_index, u32 layer) +{ + register struct nx_mlc_register_set *pregister; + register u32 regvalue; + const u32 dirtyflg_mask = 1ul << 4; + + pregister = __g_module_variables[module_index].pregister; + if (layer == 0 || layer == 1) { + regvalue = pregister->mlcrgblayer[layer].mlccontrol; + regvalue |= dirtyflg_mask; + + writel(regvalue, &pregister->mlcrgblayer[layer].mlccontrol); + } else if (layer == 3) { + regvalue = pregister->mlcvideolayer.mlccontrol; + regvalue |= dirtyflg_mask; + + writel(regvalue, &pregister->mlcvideolayer.mlccontrol); + } +} + +int nx_mlc_get_dirty_flag(u32 module_index, u32 layer) +{ + const u32 dirtyflg_pos = 4; + const u32 dirtyflg_mask = 1ul << dirtyflg_pos; + + if (layer == 0 || layer == 1) { + return (int)((__g_module_variables[module_index] + .pregister->mlcrgblayer[layer] + .mlccontrol & dirtyflg_mask) >> dirtyflg_pos); + } else if (layer == 2) { + return (int)((__g_module_variables[module_index] + .pregister->mlcrgblayer2.mlccontrol & + dirtyflg_mask) >> dirtyflg_pos); + } else if (layer == 3) { + return (int)((__g_module_variables[module_index] + .pregister->mlcvideolayer.mlccontrol & + dirtyflg_mask) >> dirtyflg_pos); + } + return 0; +} + +void nx_mlc_set_layer_enable(u32 module_index, u32 layer, int benb) +{ + const u32 layerenb_pos = 5; + const u32 layerenb_mask = 0x01 << layerenb_pos; + const u32 dirtyflag_pos = 4; + const u32 dirtyflag_mask = 1ul << dirtyflag_pos; + register u32 regvalue; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + if (layer == 0 || layer == 1) { + regvalue = pregister->mlcrgblayer[layer].mlccontrol; + regvalue &= ~(layerenb_mask | dirtyflag_mask); + regvalue |= (benb << layerenb_pos); + + writel(regvalue, &pregister->mlcrgblayer[layer].mlccontrol); + } else if (layer == 3) { + regvalue = pregister->mlcvideolayer.mlccontrol; + regvalue &= ~(layerenb_mask | dirtyflag_mask); + regvalue |= (benb << layerenb_pos); + + writel(regvalue, &pregister->mlcvideolayer.mlccontrol); + } +} + +int nx_mlc_get_layer_enable(u32 module_index, u32 layer) +{ + const u32 layerenb_pos = 5; + const u32 layerenb_mask = 0x01 << layerenb_pos; + + if (layer == 0 || layer == 1) { + return (int)((__g_module_variables[module_index] + .pregister->mlcrgblayer[layer] + .mlccontrol & layerenb_mask) >> layerenb_pos); + } else if (layer == 3) { + return (int)((__g_module_variables[module_index] + .pregister->mlcvideolayer.mlccontrol & + layerenb_mask) >> layerenb_pos); + } + return 0; +} + +void nx_mlc_set_lock_size(u32 module_index, u32 layer, u32 locksize) +{ + const u32 locksize_mask = 3ul << 12; + const u32 dirtyflag_pos = 4; + const u32 dirtyflag_mask = 1ul << dirtyflag_pos; + register struct nx_mlc_register_set *pregister; + register u32 regvalue; + + pregister = __g_module_variables[module_index].pregister; + locksize >>= 3; + if (layer == 0 || layer == 1) { + regvalue = pregister->mlcrgblayer[layer].mlccontrol; + regvalue &= ~(locksize_mask | dirtyflag_mask); + regvalue |= (locksize << 12); + + writel(regvalue, &pregister->mlcrgblayer[layer].mlccontrol); + } +} + +void nx_mlc_set_alpha_blending(u32 module_index, u32 layer, int benb, u32 alpha) +{ + const u32 blendenb_pos = 2; + const u32 blendenb_mask = 0x01 << blendenb_pos; + const u32 dirtyflag_pos = 4; + const u32 dirtyflag_mask = 1ul << dirtyflag_pos; + const u32 alpha_pos = 28; + const u32 alpha_mask = 0xf << alpha_pos; + register u32 regvalue; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + if (layer == 0 || layer == 1) { + regvalue = pregister->mlcrgblayer[layer].mlccontrol; + regvalue &= ~(blendenb_mask | dirtyflag_mask); + regvalue |= (benb << blendenb_pos); + + writel(regvalue, &pregister->mlcrgblayer[layer].mlccontrol); + regvalue = pregister->mlcrgblayer[layer].mlctpcolor; + regvalue &= ~alpha_mask; + regvalue |= alpha << alpha_pos; + + writel(regvalue, &pregister->mlcrgblayer[layer].mlctpcolor); + } else if (layer == 3) { + regvalue = pregister->mlcvideolayer.mlccontrol; + regvalue &= ~(blendenb_mask | dirtyflag_mask); + regvalue |= (benb << blendenb_pos); + + writel(regvalue, &pregister->mlcvideolayer.mlccontrol); + + writel(alpha << alpha_pos, + &pregister->mlcvideolayer.mlctpcolor); + } +} + +void nx_mlc_set_transparency(u32 module_index, u32 layer, int benb, u32 color) +{ + const u32 tpenb_pos = 0; + const u32 tpenb_mask = 0x01 << tpenb_pos; + const u32 dirtyflag_pos = 4; + const u32 dirtyflag_mask = 1ul << dirtyflag_pos; + const u32 tpcolor_pos = 0; + const u32 tpcolor_mask = ((1 << 24) - 1) << tpcolor_pos; + register u32 regvalue; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + if (layer == 0 || layer == 1) { + regvalue = pregister->mlcrgblayer[layer].mlccontrol; + regvalue &= ~(tpenb_mask | dirtyflag_mask); + regvalue |= (benb << tpenb_pos); + + writel(regvalue, &pregister->mlcrgblayer[layer].mlccontrol); + regvalue = pregister->mlcrgblayer[layer].mlctpcolor; + regvalue &= ~tpcolor_mask; + regvalue |= (color & tpcolor_mask); + + writel(regvalue, &pregister->mlcrgblayer[layer].mlctpcolor); + } +} + +void nx_mlc_set_color_inversion(u32 module_index, u32 layer, int benb, + u32 color) +{ + const u32 invenb_pos = 1; + const u32 invenb_mask = 0x01 << invenb_pos; + const u32 dirtyflag_pos = 4; + const u32 dirtyflag_mask = 1ul << dirtyflag_pos; + const u32 invcolor_pos = 0; + const u32 invcolor_mask = ((1 << 24) - 1) << invcolor_pos; + register u32 regvalue; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + if (layer == 0 || layer == 1) { + regvalue = pregister->mlcrgblayer[layer].mlccontrol; + regvalue &= ~(invenb_mask | dirtyflag_mask); + regvalue |= (benb << invenb_pos); + + writel(regvalue, &pregister->mlcrgblayer[layer].mlccontrol); + regvalue = pregister->mlcrgblayer[layer].mlcinvcolor; + regvalue &= ~invcolor_mask; + regvalue |= (color & invcolor_mask); + + writel(regvalue, &pregister->mlcrgblayer[layer].mlcinvcolor); + } +} + +u32 nx_mlc_get_extended_color(u32 module_index, u32 color, + enum nx_mlc_rgbfmt format) +{ + u32 rgb[3] = { + 0, + }; + u32 bw[3] = { + 0, + }; + u32 bp[3] = { + 0, + }; + u32 blank = 0; + u32 fill = 0; + u32 i = 0; + + switch (format) { + case nx_mlc_rgbfmt_r5g6b5: + bw[0] = 5; + bw[1] = 6; + bw[2] = 5; + bp[0] = 11; + bp[1] = 5; + bp[2] = 0; + break; + case nx_mlc_rgbfmt_b5g6r5: + bw[0] = 5; + bw[1] = 6; + bw[2] = 5; + bp[0] = 0; + bp[1] = 5; + bp[2] = 11; + break; + case nx_mlc_rgbfmt_x1r5g5b5: + case nx_mlc_rgbfmt_a1r5g5b5: + bw[0] = 5; + bw[1] = 5; + bw[2] = 5; + bp[0] = 10; + bp[1] = 5; + bp[2] = 0; + break; + case nx_mlc_rgbfmt_x1b5g5r5: + case nx_mlc_rgbfmt_a1b5g5r5: + bw[0] = 5; + bw[1] = 5; + bw[2] = 5; + bp[0] = 0; + bp[1] = 5; + bp[2] = 10; + break; + case nx_mlc_rgbfmt_x4r4g4b4: + case nx_mlc_rgbfmt_a4r4g4b4: + bw[0] = 4; + bw[1] = 4; + bw[2] = 4; + bp[0] = 8; + bp[1] = 4; + bp[2] = 0; + break; + case nx_mlc_rgbfmt_x4b4g4r4: + case nx_mlc_rgbfmt_a4b4g4r4: + bw[0] = 4; + bw[1] = 4; + bw[2] = 4; + bp[0] = 0; + bp[1] = 4; + bp[2] = 8; + break; + case nx_mlc_rgbfmt_x8r3g3b2: + case nx_mlc_rgbfmt_a8r3g3b2: + bw[0] = 3; + bw[1] = 3; + bw[2] = 2; + bp[0] = 5; + bp[1] = 2; + bp[2] = 0; + break; + case nx_mlc_rgbfmt_x8b3g3r2: + case nx_mlc_rgbfmt_a8b3g3r2: + bw[0] = 2; + bw[1] = 3; + bw[2] = 3; + bp[0] = 0; + bp[1] = 2; + bp[2] = 5; + break; + case nx_mlc_rgbfmt_r8g8b8: + case nx_mlc_rgbfmt_a8r8g8b8: + bw[0] = 8; + bw[1] = 8; + bw[2] = 8; + bp[0] = 16; + bp[1] = 8; + bp[2] = 0; + break; + case nx_mlc_rgbfmt_b8g8r8: + case nx_mlc_rgbfmt_a8b8g8r8: + bw[0] = 8; + bw[1] = 8; + bw[2] = 8; + bp[0] = 0; + bp[1] = 8; + bp[2] = 16; + break; + default: + break; + } + for (i = 0; i < 3; i++) { + rgb[i] = (color >> bp[i]) & ((u32)(1 << bw[i]) - 1); + fill = bw[i]; + blank = 8 - fill; + rgb[i] <<= blank; + while (blank > 0) { + rgb[i] |= (rgb[i] >> fill); + blank -= fill; + fill += fill; + } + } + + return (rgb[0] << 16) | (rgb[1] << 8) | (rgb[2] << 0); +} + +void nx_mlc_set_format_rgb(u32 module_index, u32 layer, + enum nx_mlc_rgbfmt format) +{ + const u32 dirtyflag_pos = 4; + const u32 dirtyflag_mask = 1ul << dirtyflag_pos; + const u32 format_mask = 0xffff0000ul; + register u32 regvalue; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + if (layer == 0 || layer == 1) { + regvalue = pregister->mlcrgblayer[layer].mlccontrol; + regvalue &= ~(format_mask | dirtyflag_mask); + regvalue |= (u32)format; + + writel(regvalue, &pregister->mlcrgblayer[layer].mlccontrol); + } +} + +void nx_mlc_set_format_yuv(u32 module_index, enum nx_mlc_yuvfmt format) +{ + const u32 format_mask = 0xffff0000ul; + register u32 temp; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + temp = pregister->mlcvideolayer.mlccontrol; + temp &= ~format_mask; + temp |= (u32)format; + + writel(temp, &pregister->mlcvideolayer.mlccontrol); +} + +void nx_mlc_set_position(u32 module_index, u32 layer, s32 sx, s32 sy, + s32 ex, s32 ey) +{ + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + if (layer == 0 || layer == 1) { + writel((((u32)sx & 0xffful) << 16) | ((u32)ex & 0xffful), + &pregister->mlcrgblayer[layer].mlcleftright); + + writel((((u32)sy & 0xffful) << 16) | ((u32)ey & 0xffful), + &pregister->mlcrgblayer[layer].mlctopbottom); + } else if (layer == 2) { + writel((((u32)sx & 0xffful) << 16) | ((u32)ex & 0xffful), + &pregister->mlcrgblayer2.mlcleftright); + + writel((((u32)sy & 0xffful) << 16) | ((u32)ey & 0xffful), + &pregister->mlcrgblayer2.mlctopbottom); + } else if (layer == 3) { + writel((((u32)sx & 0xffful) << 16) | ((u32)ex & 0xffful), + &pregister->mlcvideolayer.mlcleftright); + + writel((((u32)sy & 0xffful) << 16) | ((u32)ey & 0xffful), + &pregister->mlcvideolayer.mlctopbottom); + } +} + +void nx_mlc_set_dither_enable_when_using_gamma(u32 module_index, int benable) +{ + const u32 ditherenb_bitpos = 0; + const u32 ditherenb_mask = 1 << ditherenb_bitpos; + register struct nx_mlc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->mlcgammacont; + read_value &= ~ditherenb_mask; + read_value |= ((u32)benable << ditherenb_bitpos); + + writel(read_value, &pregister->mlcgammacont); +} + +int nx_mlc_get_dither_enable_when_using_gamma(u32 module_index) +{ + const u32 ditherenb_bitpos = 0; + const u32 ditherenb_mask = 1 << ditherenb_bitpos; + + return (int)(__g_module_variables[module_index].pregister->mlcgammacont + & ditherenb_mask); +} + +void nx_mlc_set_gamma_priority(u32 module_index, int bvideolayer) +{ + const u32 alphaselect_bitpos = 5; + const u32 alphaselect_mask = 1 << alphaselect_bitpos; + register struct nx_mlc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->mlcgammacont; + read_value &= ~alphaselect_mask; + read_value |= ((u32)bvideolayer << alphaselect_bitpos); + + writel(read_value, &pregister->mlcgammacont); +} + +int nx_mlc_get_gamma_priority(u32 module_index) +{ + const u32 alphaselect_bitpos = 5; + const u32 alphaselect_mask = 1 << alphaselect_bitpos; + + return (int)((__g_module_variables[module_index].pregister->mlcgammacont + & alphaselect_mask) >> alphaselect_bitpos); +} + +void nx_mlc_set_rgblayer_invalid_position(u32 module_index, u32 layer, + u32 region, s32 sx, s32 sy, + s32 ex, s32 ey, int benb) +{ + const u32 invalidenb_pos = 28; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + if (layer == 0 || layer == 1) { + if (region == 0) { + writel(((benb << invalidenb_pos) | + ((sx & 0x7ff) << 16) | (ex & 0x7ff)), + &pregister->mlcrgblayer[layer] + .mlcinvalidleftright0); + + writel((((sy & 0x7ff) << 16) | (ey & 0x7ff)), + &pregister->mlcrgblayer[layer] + .mlcinvalidtopbottom0); + } else { + writel(((benb << invalidenb_pos) | + ((sx & 0x7ff) << 16) | (ex & 0x7ff)), + &pregister->mlcrgblayer[layer] + .mlcinvalidleftright1); + + writel((((sy & 0x7ff) << 16) | (ey & 0x7ff)), + &pregister->mlcrgblayer[layer] + .mlcinvalidtopbottom1); + } + } +} + +void nx_mlc_set_rgblayer_stride(u32 module_index, u32 layer, s32 hstride, + s32 vstride) +{ + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + if (layer == 0 || layer == 1) { + writel(hstride, &pregister->mlcrgblayer[layer].mlchstride); + writel(vstride, &pregister->mlcrgblayer[layer].mlcvstride); + } else if (layer == 2) { + writel(hstride, &pregister->mlcrgblayer2.mlchstride); + writel(vstride, &pregister->mlcrgblayer2.mlcvstride); + } +} + +void nx_mlc_set_rgblayer_address(u32 module_index, u32 layer, u32 addr) +{ + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + if (layer == 0 || layer == 1) + writel(addr, &pregister->mlcrgblayer[layer].mlcaddress); + else if (layer == 2) + writel(addr, &pregister->mlcrgblayer2.mlcaddress); +} + +void nx_mlc_set_rgblayer_gama_table_power_mode(u32 module_index, int bred, + int bgreen, int bblue) +{ + const u32 bgammatable_pwd_bitpos = 11; + const u32 ggammatable_pwd_bitpos = 9; + const u32 rgammatable_pwd_bitpos = 3; + const u32 bgammatable_pwd_mask = (1 << bgammatable_pwd_bitpos); + const u32 ggammatable_pwd_mask = (1 << ggammatable_pwd_bitpos); + const u32 rgammatable_pwd_mask = (1 << rgammatable_pwd_bitpos); + register u32 read_value; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->mlcgammacont; + read_value &= ~(bgammatable_pwd_mask | ggammatable_pwd_mask | + rgammatable_pwd_mask); + read_value |= (((u32)bred << rgammatable_pwd_bitpos) | + ((u32)bgreen << ggammatable_pwd_bitpos) | + ((u32)bblue << bgammatable_pwd_bitpos)); + + writel(read_value, &pregister->mlcgammacont); +} + +void nx_mlc_get_rgblayer_gama_table_power_mode(u32 module_index, int *pbred, + int *pbgreen, int *pbblue) +{ + const u32 bgammatable_pwd_bitpos = 11; + const u32 ggammatable_pwd_bitpos = 9; + const u32 rgammatable_pwd_bitpos = 3; + const u32 bgammatable_pwd_mask = (1 << bgammatable_pwd_bitpos); + const u32 ggammatable_pwd_mask = (1 << ggammatable_pwd_bitpos); + const u32 rgammatable_pwd_mask = (1 << rgammatable_pwd_bitpos); + register u32 read_value; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->mlcgammacont; + if (pbred) + *pbred = (read_value & rgammatable_pwd_mask) ? 1 : 0; + + if (pbgreen) + *pbgreen = (read_value & ggammatable_pwd_mask) ? 1 : 0; + + if (pbblue) + *pbblue = (read_value & bgammatable_pwd_mask) ? 1 : 0; +} + +void nx_mlc_set_rgblayer_gama_table_sleep_mode(u32 module_index, int bred, + int bgreen, int bblue) +{ + const u32 bgammatable_sld_bitpos = 10; + const u32 ggammatable_sld_bitpos = 8; + const u32 rgammatable_sld_bitpos = 2; + const u32 bgammatable_sld_mask = (1 << bgammatable_sld_bitpos); + const u32 ggammatable_sld_mask = (1 << ggammatable_sld_bitpos); + const u32 rgammatable_sld_mask = (1 << rgammatable_sld_bitpos); + register u32 read_value; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->mlcgammacont; + if (bred) + read_value &= ~rgammatable_sld_mask; + else + read_value |= rgammatable_sld_mask; + + if (bgreen) + read_value &= ~ggammatable_sld_mask; + else + read_value |= ggammatable_sld_mask; + + if (bblue) + read_value &= ~bgammatable_sld_mask; + else + read_value |= bgammatable_sld_mask; + + writel(read_value, &pregister->mlcgammacont); +} + +void nx_mlc_get_rgblayer_gama_table_sleep_mode(u32 module_index, int *pbred, + int *pbgreen, int *pbblue) +{ + const u32 bgammatable_sld_bitpos = 10; + const u32 ggammatable_sld_bitpos = 8; + const u32 rgammatable_sld_bitpos = 2; + const u32 bgammatable_sld_mask = (1 << bgammatable_sld_bitpos); + const u32 ggammatable_sld_mask = (1 << ggammatable_sld_bitpos); + const u32 rgammatable_sld_mask = (1 << rgammatable_sld_bitpos); + register u32 read_value; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->mlcgammacont; + + if (pbred) + *pbred = (read_value & rgammatable_sld_mask) ? 0 : 1; + + if (pbgreen) + *pbgreen = (read_value & ggammatable_sld_mask) ? 0 : 1; + + if (pbblue) + *pbblue = (read_value & bgammatable_sld_mask) ? 0 : 1; +} + +void nx_mlc_set_rgblayer_rgamma_table(u32 module_index, u32 dwaddress, + u32 dwdata) +{ + register struct nx_mlc_register_set *pregister; + const u32 tableaddr_bitpos = 24; + + pregister = __g_module_variables[module_index].pregister; + writel(((dwaddress << tableaddr_bitpos) | dwdata), + &pregister->mlcrgammatablewrite); +} + +void nx_mlc_set_rgblayer_ggamma_table(u32 module_index, u32 dwaddress, + u32 dwdata) +{ + register struct nx_mlc_register_set *pregister; + const u32 tableaddr_bitpos = 24; + + pregister = __g_module_variables[module_index].pregister; + writel(((dwaddress << tableaddr_bitpos) | dwdata), + &pregister->mlcggammatablewrite); +} + +void nx_mlc_set_rgblayer_bgamma_table(u32 module_index, u32 dwaddress, + u32 dwdata) +{ + register struct nx_mlc_register_set *pregister; + const u32 tableaddr_bitpos = 24; + + pregister = __g_module_variables[module_index].pregister; + writel(((dwaddress << tableaddr_bitpos) | dwdata), + &pregister->mlcbgammatablewrite); +} + +void nx_mlc_set_rgblayer_gamma_enable(u32 module_index, int benable) +{ + const u32 rgbgammaemb_bitpos = 1; + const u32 rgbgammaemb_mask = 1 << rgbgammaemb_bitpos; + register u32 read_value; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->mlcgammacont; + read_value &= ~rgbgammaemb_mask; + read_value |= (u32)benable << rgbgammaemb_bitpos; + + writel(read_value, &pregister->mlcgammacont); +} + +int nx_mlc_get_rgblayer_gamma_enable(u32 module_index) +{ + const u32 rgbgammaemb_bitpos = 1; + const u32 rgbgammaemb_mask = 1 << rgbgammaemb_bitpos; + + return (int)((__g_module_variables[module_index].pregister->mlcgammacont + & rgbgammaemb_mask) >> rgbgammaemb_bitpos); +} + +void nx_mlc_set_video_layer_stride(u32 module_index, s32 lu_stride, + s32 cb_stride, s32 cr_stride) +{ + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + writel(lu_stride, &pregister->mlcvideolayer.mlcvstride); + writel(cb_stride, &pregister->mlcvideolayer.mlcvstridecb); + writel(cr_stride, &pregister->mlcvideolayer.mlcvstridecr); +} + +void nx_mlc_set_video_layer_address(u32 module_index, u32 lu_addr, u32 cb_addr, + u32 cr_addr) +{ + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel(lu_addr, &pregister->mlcvideolayer.mlcaddress); + writel(cb_addr, &pregister->mlcvideolayer.mlcaddresscb); + writel(cr_addr, &pregister->mlcvideolayer.mlcaddresscr); +} + +void nx_mlc_set_video_layer_address_yuyv(u32 module_index, u32 addr, + s32 stride) +{ + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel(addr, &pregister->mlcvideolayer.mlcaddress); + writel(stride, &pregister->mlcvideolayer.mlcvstride); +} + +void nx_mlc_set_video_layer_scale_factor(u32 module_index, u32 hscale, + u32 vscale, int bhlumaenb, + int bhchromaenb, int bvlumaenb, + int bvchromaenb) +{ + const u32 filter_luma_pos = 28; + const u32 filter_choma_pos = 29; + const u32 scale_mask = ((1 << 23) - 1); + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + writel(((bhlumaenb << filter_luma_pos) | + (bhchromaenb << filter_choma_pos) | (hscale & scale_mask)), + &pregister->mlcvideolayer.mlchscale); + + writel(((bvlumaenb << filter_luma_pos) | + (bvchromaenb << filter_choma_pos) | (vscale & scale_mask)), + &pregister->mlcvideolayer.mlcvscale); +} + +void nx_mlc_set_video_layer_scale_filter(u32 module_index, int bhlumaenb, + int bhchromaenb, int bvlumaenb, + int bvchromaenb) +{ + const u32 filter_luma_pos = 28; + const u32 filter_choma_pos = 29; + const u32 scale_mask = ((1 << 23) - 1); + register struct nx_mlc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->mlcvideolayer.mlchscale; + read_value &= scale_mask; + read_value |= + (bhlumaenb << filter_luma_pos) | (bhchromaenb << filter_choma_pos); + + writel(read_value, &pregister->mlcvideolayer.mlchscale); + read_value = pregister->mlcvideolayer.mlcvscale; + read_value &= scale_mask; + read_value |= + (bvlumaenb << filter_luma_pos) | (bvchromaenb << filter_choma_pos); + + writel(read_value, &pregister->mlcvideolayer.mlcvscale); +} + +void nx_mlc_get_video_layer_scale_filter(u32 module_index, int *bhlumaenb, + int *bhchromaenb, int *bvlumaenb, + int *bvchromaenb) +{ + const u32 filter_luma_pos = 28; + const u32 filter_choma_pos = 29; + const u32 filter_mask = 1ul; + register struct nx_mlc_register_set *pregister; + register u32 read_value; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->mlcvideolayer.mlchscale; + *bhlumaenb = (read_value >> filter_luma_pos) & filter_mask; + *bhchromaenb = (read_value >> filter_choma_pos) & filter_mask; + read_value = pregister->mlcvideolayer.mlcvscale; + *bvlumaenb = (read_value >> filter_luma_pos) & filter_mask; + *bvchromaenb = (read_value >> filter_choma_pos) & filter_mask; +} + +void nx_mlc_set_video_layer_scale(u32 module_index, u32 sw, u32 sh, u32 dw, + u32 dh, int bhlumaenb, int bhchromaenb, + int bvlumaenb, int bvchromaenb) +{ + const u32 filter_luma_pos = 28; + const u32 filter_choma_pos = 29; + const u32 scale_mask = ((1 << 23) - 1); + register u32 hscale, vscale, cal_sh; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + if ((bhlumaenb || bhchromaenb) && dw > sw) { + sw--; + dw--; + } + hscale = (sw << 11) / dw; + + if ((bvlumaenb || bvchromaenb) && dh > sh) { + sh--; + dh--; + vscale = (sh << 11) / dh; + + cal_sh = ((vscale * dh) >> 11); + if (sh <= cal_sh) + vscale--; + + } else { + vscale = (sh << 11) / dh; + } + + writel(((bhlumaenb << filter_luma_pos) | + (bhchromaenb << filter_choma_pos) | (hscale & scale_mask)), + &pregister->mlcvideolayer.mlchscale); + + writel(((bvlumaenb << filter_luma_pos) | + (bvchromaenb << filter_choma_pos) | (vscale & scale_mask)), + &pregister->mlcvideolayer.mlcvscale); +} + +void nx_mlc_set_video_layer_luma_enhance(u32 module_index, u32 contrast, + s32 brightness) +{ + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + writel((((u32)brightness & 0xfful) << 8) | contrast, + &pregister->mlcvideolayer.mlcluenh); +} + +void nx_mlc_set_video_layer_chroma_enhance(u32 module_index, u32 quadrant, + s32 cb_a, s32 cb_b, + s32 cr_a, s32 cr_b) +{ + register struct nx_mlc_register_set *pregister; + register u32 temp; + + pregister = __g_module_variables[module_index].pregister; + temp = (((u32)cr_b & 0xfful) << 24) | (((u32)cr_a & 0xfful) << 16) | + (((u32)cb_b & 0xfful) << 8) | (((u32)cb_a & 0xfful) << 0); + if (quadrant > 0) { + writel(temp, &pregister->mlcvideolayer.mlcchenh[quadrant - 1]); + } else { + writel(temp, &pregister->mlcvideolayer.mlcchenh[0]); + writel(temp, &pregister->mlcvideolayer.mlcchenh[1]); + writel(temp, &pregister->mlcvideolayer.mlcchenh[2]); + writel(temp, &pregister->mlcvideolayer.mlcchenh[3]); + } +} + +void nx_mlc_set_video_layer_line_buffer_power_mode(u32 module_index, + int benable) +{ + const u32 linebuff_pwd_pos = 15; + const u32 linebuff_pwd_mask = 1ul << linebuff_pwd_pos; + const u32 dirtyflag_mask = 1ul << 4; + register u32 regvalue; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + regvalue = pregister->mlcvideolayer.mlccontrol; + regvalue &= ~(linebuff_pwd_mask | dirtyflag_mask); + regvalue |= ((u32)benable << linebuff_pwd_pos); + + writel(regvalue, &pregister->mlcvideolayer.mlccontrol); +} + +int nx_mlc_get_video_layer_line_buffer_power_mode(u32 module_index) +{ + const u32 linebuff_pwd_pos = 15; + const u32 linebuff_pwd_mask = 1ul << linebuff_pwd_pos; + + return (int)((__g_module_variables[module_index] + .pregister->mlcvideolayer.mlccontrol & + linebuff_pwd_mask) >> linebuff_pwd_pos); +} + +void nx_mlc_set_video_layer_line_buffer_sleep_mode(u32 module_index, + int benable) +{ + const u32 linebuff_slmd_pos = 14; + const u32 linebuff_slmd_mask = 1ul << linebuff_slmd_pos; + const u32 dirtyflag_mask = 1ul << 4; + register u32 regvalue; + register struct nx_mlc_register_set *pregister; + + benable = (int)((u32)benable ^ 1); + pregister = __g_module_variables[module_index].pregister; + regvalue = pregister->mlcvideolayer.mlccontrol; + regvalue &= ~(linebuff_slmd_mask | dirtyflag_mask); + regvalue |= (benable << linebuff_slmd_pos); + + writel(regvalue, &pregister->mlcvideolayer.mlccontrol); +} + +int nx_mlc_get_video_layer_line_buffer_sleep_mode(u32 module_index) +{ + const u32 linebuff_slmd_pos = 14; + const u32 linebuff_slmd_mask = 1ul << linebuff_slmd_pos; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + if (linebuff_slmd_mask & pregister->mlcvideolayer.mlccontrol) + return 0; + else + return 1; +} + +void nx_mlc_set_video_layer_gama_table_power_mode(u32 module_index, int by, + int bu, int bv) +{ + const u32 vgammatable_pwd_bitpos = 17; + const u32 ugammatable_pwd_bitpos = 15; + const u32 ygammatable_pwd_bitpos = 13; + const u32 vgammatable_pwd_mask = (1 << vgammatable_pwd_bitpos); + const u32 ugammatable_pwd_mask = (1 << ugammatable_pwd_bitpos); + const u32 ygammatable_pwd_mask = (1 << ygammatable_pwd_bitpos); + register u32 read_value; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->mlcgammacont; + read_value &= ~(ygammatable_pwd_mask | ugammatable_pwd_mask | + vgammatable_pwd_mask); + read_value |= (((u32)by << ygammatable_pwd_bitpos) | + ((u32)bu << ugammatable_pwd_bitpos) | + ((u32)bv << vgammatable_pwd_bitpos)); + + writel(read_value, &pregister->mlcgammacont); +} + +void nx_mlc_get_video_layer_gama_table_power_mode(u32 module_index, int *pby, + int *pbu, int *pbv) +{ + const u32 vgammatable_pwd_bitpos = 17; + const u32 ugammatable_pwd_bitpos = 15; + const u32 ygammatable_pwd_bitpos = 13; + const u32 vgammatable_pwd_mask = (1 << vgammatable_pwd_bitpos); + const u32 ugammatable_pwd_mask = (1 << ugammatable_pwd_bitpos); + const u32 ygammatable_pwd_mask = (1 << ygammatable_pwd_bitpos); + register u32 read_value; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->mlcgammacont; + if (pby) + *pby = (read_value & ygammatable_pwd_mask) ? 1 : 0; + + if (pbu) + *pbu = (read_value & ugammatable_pwd_mask) ? 1 : 0; + + if (pbv) + *pbv = (read_value & vgammatable_pwd_mask) ? 1 : 0; +} + +void nx_mlc_set_video_layer_gama_table_sleep_mode(u32 module_index, int by, + int bu, int bv) +{ + const u32 vgammatable_sld_bitpos = 16; + const u32 ugammatable_sld_bitpos = 14; + const u32 ygammatable_sld_bitpos = 12; + const u32 vgammatable_sld_mask = (1 << vgammatable_sld_bitpos); + const u32 ugammatable_sld_mask = (1 << ugammatable_sld_bitpos); + const u32 ygammatable_sld_mask = (1 << ygammatable_sld_bitpos); + register u32 read_value; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->mlcgammacont; + if (by) + read_value &= ~ygammatable_sld_mask; + else + read_value |= ygammatable_sld_mask; + + if (bu) + read_value &= ~ugammatable_sld_mask; + else + read_value |= ugammatable_sld_mask; + + if (bv) + read_value &= ~vgammatable_sld_mask; + else + read_value |= vgammatable_sld_mask; + + writel(read_value, &pregister->mlcgammacont); +} + +void nx_mlc_get_video_layer_gama_table_sleep_mode(u32 module_index, int *pby, + int *pbu, int *pbv) +{ + const u32 vgammatable_sld_bitpos = 16; + const u32 ugammatable_sld_bitpos = 14; + const u32 ygammatable_sld_bitpos = 12; + const u32 vgammatable_sld_mask = (1 << vgammatable_sld_bitpos); + const u32 ugammatable_sld_mask = (1 << ugammatable_sld_bitpos); + const u32 ygammatable_sld_mask = (1 << ygammatable_sld_bitpos); + register u32 read_value; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->mlcgammacont; + + if (pby) + *pby = (read_value & vgammatable_sld_mask) ? 0 : 1; + + if (pbu) + *pbu = (read_value & ugammatable_sld_mask) ? 0 : 1; + + if (pbv) + *pbv = (read_value & ygammatable_sld_mask) ? 0 : 1; +} + +void nx_mlc_set_video_layer_gamma_enable(u32 module_index, int benable) +{ + const u32 yuvgammaemb_bitpos = 4; + const u32 yuvgammaemb_mask = 1 << yuvgammaemb_bitpos; + register u32 read_value; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + read_value = pregister->mlcgammacont; + read_value &= ~yuvgammaemb_mask; + read_value |= (u32)benable << yuvgammaemb_bitpos; + + writel(read_value, &pregister->mlcgammacont); +} + +int nx_mlc_get_video_layer_gamma_enable(u32 module_index) +{ + const u32 yuvgammaemb_bitpos = 4; + const u32 yuvgammaemb_mask = 1 << yuvgammaemb_bitpos; + + return (int)((__g_module_variables[module_index].pregister->mlcgammacont + & yuvgammaemb_mask) >> yuvgammaemb_bitpos); +} + +void nx_mlc_set_gamma_table_poweroff(u32 module_index, int enb) +{ + register struct nx_mlc_register_set *pregister; + u32 regvalue; + + pregister = __g_module_variables[module_index].pregister; + if (enb == 1) { + regvalue = pregister->mlcgammacont; + regvalue = regvalue & 0xf3; + writel(regvalue, &pregister->mlcgammacont); + } +} + +void nx_mlc_set_mlctop_control_parameter(u32 module_index, int field_enable, + int mlcenable, u8 priority, + enum g3daddrchangeallowed + g3daddr_change_allowed) +{ + register u32 mlctopcontrolreg; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + mlctopcontrolreg = (readl(&pregister->mlccontrolt)) & 0xfffffcfc; + mlctopcontrolreg = (u32)(mlctopcontrolreg | + ((priority << 8) | ((mlcenable == 1) << 1) | + (1 == + field_enable)) | (g3daddr_change_allowed << + 12)); + writel(mlctopcontrolreg, &pregister->mlccontrolt); +} + +void nx_mlc_set_rgb0layer_control_parameter(u32 module_index, int layer_enable, + int grp3denable, int tp_enable, + u32 transparency_color, + int inv_enable, u32 inverse_color, + int blend_enable, u8 alpha_value, + enum mlc_rgbfmt rbgformat, + enum locksizesel lock_size_select) +{ + u32 layer_format; + u32 control_enb; + u32 alpha_argument; + u32 lock_size = (u32)(lock_size_select & 0x3); + u32 rgb0controlreg; + u32 regvalue; + register struct nx_mlc_register_set *pregister; + + layer_format = nx_mlc_get_rgbformat(rbgformat); + pregister = __g_module_variables[module_index].pregister; + control_enb = + (u32)((grp3denable << 8) | (layer_enable << 5) | + (blend_enable << 2) | (inv_enable << 1) | tp_enable) & 0x127; + alpha_argument = (u32)(alpha_value & 0xf); + + rgb0controlreg = readl(&pregister->mlcrgblayer[0].mlccontrol) & 0x10; + regvalue = + (u32)(((layer_format << 16) | control_enb | (lock_size << 12)) | + rgb0controlreg); + writel(regvalue, &pregister->mlcrgblayer[0].mlccontrol); + + regvalue = (u32)((alpha_argument << 28) | transparency_color); + writel(regvalue, &pregister->mlcrgblayer[0].mlctpcolor); + regvalue = inverse_color; + writel(regvalue, &pregister->mlcrgblayer[0].mlcinvcolor); +} + +u32 nx_mlc_get_rgbformat(enum mlc_rgbfmt rbgformat) +{ + u32 rgbformatvalue; + const u32 format_table[] = { + 0x4432ul, 0x4342ul, 0x4211ul, 0x4120ul, 0x4003ul, 0x4554ul, + 0x3342ul, 0x2211ul, 0x1120ul, 0x1003ul, 0x4653ul, 0x4653ul, + 0x0653ul, 0x4ed3ul, 0x4f84ul, 0xc432ul, 0xc342ul, 0xc211ul, + 0xc120ul, 0xb342ul, 0xa211ul, 0x9120ul, 0xc653ul, 0xc653ul, + 0x8653ul, 0xced3ul, 0xcf84ul, 0x443aul + }; + + return rgbformatvalue = format_table[rbgformat]; +} + +void nx_mlc_set_rgb1layer_control_parameter(u32 module_index, int layer_enable, + int grp3denable, int tp_enable, + u32 transparency_color, + int inv_enable, u32 inverse_color, + int blend_enable, u8 alpha_value, + enum mlc_rgbfmt rbgformat, + enum locksizesel lock_size_select) +{ + u32 layer_format; + u32 control_enb; + u32 alpha_argument; + u32 lock_size = (u32)(lock_size_select & 0x3); + u32 rgb0controlreg; + u32 regvalue; + register struct nx_mlc_register_set *pregister; + + layer_format = nx_mlc_get_rgbformat(rbgformat); + pregister = __g_module_variables[module_index].pregister; + + rgb0controlreg = readl(&pregister->mlcrgblayer[1].mlccontrol) & 0x10; + control_enb = + (u32)((grp3denable << 8) | (layer_enable << 5) | + (blend_enable << 2) | (inv_enable << 1) | tp_enable) & 0x127; + alpha_argument = (u32)(alpha_value & 0xf); + regvalue = + (u32)(((layer_format << 16) | control_enb | (lock_size << 12)) | + rgb0controlreg); + writel(regvalue, &pregister->mlcrgblayer[1].mlccontrol); + regvalue = (u32)((alpha_argument << 28) | transparency_color); + writel(regvalue, &pregister->mlcrgblayer[1].mlctpcolor); + regvalue = inverse_color; + writel(regvalue, &pregister->mlcrgblayer[1].mlcinvcolor); +} + +void nx_mlc_set_rgb2layer_control_parameter(u32 module_index, int layer_enable, + int grp3denable, int tp_enable, + u32 transparency_color, + int inv_enable, u32 inverse_color, + int blend_enable, u8 alpha_value, + enum mlc_rgbfmt rbgformat, + enum locksizesel lock_size_select) +{ + u32 layer_format; + u32 control_enb; + u32 alpha_argument; + u32 lock_size = (u32)(lock_size_select & 0x3); + u32 rgb0controlreg; + u32 regvalue; + register struct nx_mlc_register_set *pregister; + + layer_format = nx_mlc_get_rgbformat(rbgformat); + pregister = __g_module_variables[module_index].pregister; + + rgb0controlreg = readl(&pregister->mlcrgblayer2.mlccontrol) & 0x10; + control_enb = + (u32)((grp3denable << 8) | (layer_enable << 5) | + (blend_enable << 2) | (inv_enable << 1) | tp_enable) & 0x127; + alpha_argument = (u32)(alpha_value & 0xf); + regvalue = + (u32)(((layer_format << 16) | control_enb | (lock_size << 12)) | + rgb0controlreg); + writel(regvalue, &pregister->mlcrgblayer2.mlccontrol); + regvalue = (u32)((alpha_argument << 28) | transparency_color); + writel(regvalue, &pregister->mlcrgblayer2.mlctpcolor); + regvalue = inverse_color; + writel(regvalue, &pregister->mlcrgblayer2.mlcinvcolor); +} + +void nx_mlc_set_video_layer_control_parameter(u32 module_index, + int layer_enable, int tp_enable, + u32 transparency_color, + int inv_enable, u32 inverse_color, + int blend_enable, u8 alpha_value, + enum nx_mlc_yuvfmt yuvformat) +{ + u32 control_enb; + u32 alpha_argument; + u32 regvalue; + register struct nx_mlc_register_set *pregister; + u32 video_control_reg; + + pregister = __g_module_variables[module_index].pregister; + + video_control_reg = readl(&pregister->mlcvideolayer.mlccontrol); + control_enb = + (u32)((yuvformat) | (layer_enable << 5) | (blend_enable << 2) | + (inv_enable << 1) | tp_enable) & 0x30027; + alpha_argument = (u32)(alpha_value & 0xf); + regvalue = (u32)(control_enb | video_control_reg); + writel(regvalue, &pregister->mlcvideolayer.mlccontrol); + regvalue = (u32)((alpha_argument << 28) | transparency_color); + writel(regvalue, &pregister->mlcvideolayer.mlctpcolor); + regvalue = (u32)((alpha_argument << 28) | transparency_color); + writel(regvalue, &pregister->mlcvideolayer.mlcinvcolor); +} + +void nx_mlc_set_srammode(u32 module_index, enum latyername layer_name, + enum srammode sram_mode) +{ + u32 control_reg_value; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + switch (layer_name) { + case topmlc: + control_reg_value = readl(&pregister->mlccontrolt); + writel((u32)(control_reg_value | (sram_mode << 10)), + &pregister->mlccontrolt); + control_reg_value = 0; + break; + case rgb0: + control_reg_value = + readl(&pregister->mlcrgblayer[0].mlccontrol); + writel((u32)(control_reg_value | (sram_mode << 14)), + &pregister->mlcrgblayer[0].mlccontrol); + control_reg_value = 0; + break; + case rgb1: + control_reg_value = + readl(&pregister->mlcrgblayer[1].mlccontrol); + writel((u32)(control_reg_value | (sram_mode << 14)), + &pregister->mlcrgblayer[1].mlccontrol); + control_reg_value = 0; + break; + case rgb2: + control_reg_value = readl(&pregister->mlcrgblayer2.mlccontrol); + writel((u32)(control_reg_value | (sram_mode << 14)), + &pregister->mlcrgblayer2.mlccontrol); + control_reg_value = 0; + break; + case video: + control_reg_value = readl(&pregister->mlcvideolayer.mlccontrol); + writel((u32)(control_reg_value | (sram_mode << 14)), + &pregister->mlcvideolayer.mlccontrol); + control_reg_value = 0; + break; + default: + break; + } +} + +void nx_mlc_set_layer_reg_finish(u32 module_index, enum latyername layer_name) +{ + u32 control_reg_value; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + switch (layer_name) { + case topmlc: + control_reg_value = readl(&pregister->mlccontrolt); + writel((u32)(control_reg_value | (1ul << 3)), + &pregister->mlccontrolt); + control_reg_value = 0; + break; + case rgb0: + control_reg_value = + readl(&pregister->mlcrgblayer[0].mlccontrol); + writel((u32)(control_reg_value | (1ul << 4)), + &pregister->mlcrgblayer[0].mlccontrol); + control_reg_value = 0; + break; + case rgb1: + control_reg_value = + readl(&pregister->mlcrgblayer[1].mlccontrol); + writel((u32)(control_reg_value | (1ul << 4)), + &pregister->mlcrgblayer[1].mlccontrol); + control_reg_value = 0; + break; + case rgb2: + control_reg_value = readl(&pregister->mlcrgblayer2.mlccontrol); + writel((u32)(control_reg_value | (1ul << 4)), + &pregister->mlcrgblayer2.mlccontrol); + control_reg_value = 0; + break; + case video: + control_reg_value = readl(&pregister->mlcvideolayer.mlccontrol); + writel((u32)(control_reg_value | (1ul << 4)), + &pregister->mlcvideolayer.mlccontrol); + control_reg_value = 0; + break; + default: + break; + } +} + +void nx_mlc_set_video_layer_coordinate(u32 module_index, int vfilterenable, + int hfilterenable, int vfilterenable_c, + int hfilterenable_c, + u16 video_layer_with, + u16 video_layer_height, s16 left, + s16 right, s16 top, + s16 bottom) +{ + s32 source_width, source_height; + s32 destination_width; + s32 destination_height; + s32 hscale, vscale; + s32 hfilterenb, vfilterenb; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + writel((s32)(((left & 0x0fff) << 16) | (right & 0x0fff)), + &pregister->mlcvideolayer.mlcleftright); + writel((s32)(((top & 0x0fff) << 16) | (bottom & 0x0fff)), + &pregister->mlcvideolayer.mlctopbottom); + source_width = (s32)(video_layer_with - 1); + source_height = (s32)(video_layer_height - 1); + destination_width = (s32)(right - left); + destination_height = (s32)(bottom - top); + + hscale = + (s32)((source_width * (1ul << 11) + (destination_width / 2)) / + destination_width); + vscale = + (s32)((source_height * (1ul << 11) + + (destination_height / 2)) / destination_height); + + hfilterenb = (u32)(((hfilterenable_c << 29) | (hfilterenable) << 28)) & + 0x30000000; + vfilterenb = (u32)(((vfilterenable_c << 29) | (vfilterenable) << 28)) & + 0x30000000; + writel((u32)(hfilterenb | (hscale & 0x00ffffff)), + &pregister->mlcvideolayer.mlchscale); + writel((u32)(vfilterenb | (vscale & 0x00ffffff)), + &pregister->mlcvideolayer.mlcvscale); +} + +void nx_mlc_set_video_layer_filter_scale(u32 module_index, u32 hscale, + u32 vscale) +{ + register struct nx_mlc_register_set *pregister; + u32 mlchscale = 0; + u32 mlcvscale = 0; + + pregister = __g_module_variables[module_index].pregister; + mlchscale = readl(&pregister->mlcvideolayer.mlchscale) & (~0x00ffffff); + mlcvscale = readl(&pregister->mlcvideolayer.mlcvscale) & (~0x00ffffff); + + writel((u32)(mlchscale | (hscale & 0x00ffffff)), + &pregister->mlcvideolayer.mlchscale); + writel((u32)(mlcvscale | (vscale & 0x00ffffff)), + &pregister->mlcvideolayer.mlcvscale); +} + +void nx_mlc_set_gamma_control_parameter(u32 module_index, int rgbgammaenb, + int yuvgammaenb, int yuvalphaarray, + int dither_enb) +{ + u32 register_data; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + register_data = readl(&pregister->mlcgammacont); + register_data = (register_data & 0xf0c) | + ((yuvalphaarray << 5) | (yuvgammaenb << 4) | + (rgbgammaenb << 1) | (dither_enb << 0)); + writel(register_data, &pregister->mlcgammacont); +} + +void nx_mlc_set_layer_alpha256(u32 module_index, u32 layer, u32 alpha) +{ + u32 register_data; + register struct nx_mlc_register_set *pregister; + + if (alpha < 0) + alpha = 0; + if (alpha > 255) + alpha = 255; + + pregister = __g_module_variables[module_index].pregister; + if (layer == 0) { + register_data = + readl(&pregister->mlcrgblayer[0].mlctpcolor) & 0x00ffffff; + register_data = register_data | (alpha << 24); + writel(register_data, &pregister->mlcrgblayer[0].mlctpcolor); + } else if (layer == 1) { + register_data = + readl(&pregister->mlcrgblayer[1].mlctpcolor) & 0x00ffffff; + register_data = register_data | (alpha << 24); + writel(register_data, &pregister->mlcrgblayer[1].mlctpcolor); + } else if (layer == 2) { + register_data = + readl(&pregister->mlcrgblayer[1].mlctpcolor) & 0x00ffffff; + register_data = register_data | (alpha << 24); + writel(register_data, &pregister->mlcrgblayer2.mlctpcolor); + } else { + register_data = + readl(&pregister->mlcvideolayer.mlctpcolor) & 0x00ffffff; + register_data = register_data | (alpha << 24); + writel(register_data, &pregister->mlcvideolayer.mlctpcolor); + } +} + +int nx_mlc_is_under_flow(u32 module_index) +{ + const u32 underflow_pend_pos = 31; + const u32 underflow_pend_mask = 1ul << underflow_pend_pos; + + return (int)((__g_module_variables[module_index].pregister->mlccontrolt + & underflow_pend_mask) >> underflow_pend_pos); +} + +void nx_mlc_set_gamma_table(u32 module_index, int enb, + struct nx_mlc_gamma_table_parameter *p_gammatable) +{ + register struct nx_mlc_register_set *pregister; + u32 i, regval = 0; + + pregister = __g_module_variables[module_index].pregister; + if (enb == 1) { + regval = readl(&pregister->mlcgammacont); + + regval = (1 << 11) | (1 << 9) | (1 << 3); + writel(regval, &pregister->mlcgammacont); + + regval = regval | (1 << 10) | (1 << 8) | (1 << 2); + writel(regval, &pregister->mlcgammacont); + + for (i = 0; i < 256; i++) { + nx_mlc_set_rgblayer_rgamma_table(module_index, i, + p_gammatable->r_table[i]); + nx_mlc_set_rgblayer_ggamma_table(module_index, i, + p_gammatable->g_table[i]); + nx_mlc_set_rgblayer_bgamma_table(module_index, i, + p_gammatable->b_table[i]); + } + + regval = regval | (p_gammatable->alphaselect << 5) | + (p_gammatable->yuvgammaenb << 4 | + p_gammatable->allgammaenb << 4) | + (p_gammatable->rgbgammaenb << 1 | + p_gammatable->allgammaenb << 1) | + (p_gammatable->ditherenb << 1); + writel(regval, &pregister->mlcgammacont); + } else { + regval = regval & ~(1 << 10) & ~(1 << 8) & ~(1 << 2); + writel(regval, &pregister->mlcgammacont); + + regval = regval & ~(1 << 11) & ~(1 << 9) & ~(1 << 3); + writel(regval, &pregister->mlcgammacont); + } +} + +void nx_mlc_get_rgblayer_stride(u32 module_index, u32 layer, s32 *hstride, + s32 *vstride) +{ + unsigned int hs, vs; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + hs = readl(&pregister->mlcrgblayer[layer].mlchstride); + vs = readl(&pregister->mlcrgblayer[layer].mlcvstride); + + if (hstride) + *(s32 *)hstride = hs; + + if (vstride) + *(s32 *)vstride = vs; +} + +void nx_mlc_get_rgblayer_address(u32 module_index, u32 layer, + u32 *phys_address) +{ + u32 pa; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + pa = readl(&pregister->mlcrgblayer[layer].mlcaddress); + + if (phys_address) + *(u32 *)phys_address = pa; +} + +void nx_mlc_get_position(u32 module_index, u32 layer, int *left, int *top, + int *right, int *bottom) +{ + int lr, tb; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + lr = readl(&pregister->mlcrgblayer[layer].mlcleftright); + tb = readl(&pregister->mlcrgblayer[layer].mlctopbottom); + + if (left) + *(int *)left = ((lr >> 16) & 0xFFUL); + + if (top) + *(int *)top = ((tb >> 16) & 0xFFUL); + + if (right) + *(int *)right = ((lr >> 0) & 0xFFUL); + + if (bottom) + *(int *)bottom = ((tb >> 0) & 0xFFUL); +} + +void nx_mlc_get_video_layer_address_yuyv(u32 module_index, u32 *address, + u32 *stride) +{ + u32 a, s; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + a = readl(&pregister->mlcvideolayer.mlcaddress); + s = readl(&pregister->mlcvideolayer.mlcvstride); + + if (address) + *(u32 *)address = a; + + if (stride) + *(u32 *)stride = s; +} + +void nx_mlc_get_video_layer_address(u32 module_index, u32 *lu_address, + u32 *cb_address, u32 *cr_address) +{ + u32 lua, cba, cra; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + lua = readl(&pregister->mlcvideolayer.mlcaddress); + cba = readl(&pregister->mlcvideolayer.mlcaddresscb); + cra = readl(&pregister->mlcvideolayer.mlcaddresscr); + + if (lu_address) + *(u32 *)lu_address = lua; + + if (cb_address) + *(u32 *)cb_address = cba; + + if (cr_address) + *(u32 *)cr_address = cra; +} + +void nx_mlc_get_video_layer_stride(u32 module_index, u32 *lu_stride, + u32 *cb_stride, u32 *cr_stride) +{ + u32 lus, cbs, crs; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + lus = readl(&pregister->mlcvideolayer.mlcvstride); + cbs = readl(&pregister->mlcvideolayer.mlcvstridecb); + crs = readl(&pregister->mlcvideolayer.mlcvstridecr); + + if (lu_stride) + *(u32 *)lu_stride = lus; + + if (cb_stride) + *(u32 *)cb_stride = cbs; + + if (cr_stride) + *(u32 *)cr_stride = crs; +} + +void nx_mlc_get_video_position(u32 module_index, int *left, int *top, + int *right, int *bottom) +{ + int lr, tb; + register struct nx_mlc_register_set *pregister; + + pregister = __g_module_variables[module_index].pregister; + + lr = readl(&pregister->mlcvideolayer.mlcleftright); + tb = readl(&pregister->mlcvideolayer.mlctopbottom); + + if (left) + *(int *)left = ((lr >> 16) & 0xFFUL); + + if (top) + *(int *)top = ((tb >> 16) & 0xFFUL); + + if (right) + *(int *)right = ((lr >> 0) & 0xFFUL); + + if (bottom) + *(int *)bottom = ((tb >> 0) & 0xFFUL); +} diff --git a/drivers/video/nexell/soc/s5pxx18_soc_mlc.h b/drivers/video/nexell/soc/s5pxx18_soc_mlc.h new file mode 100644 index 0000000000..77ceca6bd6 --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_mlc.h @@ -0,0 +1,429 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#ifndef _S5PXX18_SOC_MLC_H_ +#define _S5PXX18_SOC_MLC_H_ + +#include "s5pxx18_soc_disptype.h" + +#define NUMBER_OF_MLC_MODULE 2 +#define PHY_BASEADDR_MLC0 0xC0102000 +#define PHY_BASEADDR_MLC1 0xC0102400 + +#define PHY_BASEADDR_MLC_LIST \ + { PHY_BASEADDR_MLC0, PHY_BASEADDR_MLC1 } + +struct nx_mlc_register_set { + u32 mlccontrolt; + u32 mlcscreensize; + u32 mlcbgcolor; + struct { + u32 mlcleftright; + u32 mlctopbottom; + u32 mlcinvalidleftright0; + u32 mlcinvalidtopbottom0; + u32 mlcinvalidleftright1; + u32 mlcinvalidtopbottom1; + u32 mlccontrol; + s32 mlchstride; + s32 mlcvstride; + u32 mlctpcolor; + u32 mlcinvcolor; + u32 mlcaddress; + u32 __reserved0; + } mlcrgblayer[2]; + struct { + u32 mlcleftright; + u32 mlctopbottom; + u32 mlccontrol; + u32 mlcvstride; + u32 mlctpcolor; + + u32 mlcinvcolor; + u32 mlcaddress; + u32 mlcaddresscb; + u32 mlcaddresscr; + s32 mlcvstridecb; + s32 mlcvstridecr; + u32 mlchscale; + u32 mlcvscale; + u32 mlcluenh; + u32 mlcchenh[4]; + } mlcvideolayer; + struct { + u32 mlcleftright; + u32 mlctopbottom; + u32 mlcinvalidleftright0; + u32 mlcinvalidtopbottom0; + u32 mlcinvalidleftright1; + u32 mlcinvalidtopbottom1; + u32 mlccontrol; + s32 mlchstride; + s32 mlcvstride; + u32 mlctpcolor; + u32 mlcinvcolor; + u32 mlcaddress; + } mlcrgblayer2; + u32 mlcpaletetable2; + u32 mlcgammacont; + u32 mlcrgammatablewrite; + u32 mlcggammatablewrite; + u32 mlcbgammatablewrite; + u32 yuvlayergammatable_red; + u32 yuvlayergammatable_green; + u32 yuvlayergammatable_blue; + + u32 dimctrl; + u32 dimlut0; + u32 dimlut1; + u32 dimbusyflag; + u32 dimprdarrr0; + u32 dimprdarrr1; + u32 dimram0rddata; + u32 dimram1rddata; + u32 __reserved2[(0x3c0 - 0x12c) / 4]; + u32 mlcclkenb; +}; + +enum nx_mlc_priority { + nx_mlc_priority_videofirst = 0ul, + nx_mlc_priority_videosecond = 1ul, + nx_mlc_priority_videothird = 2ul, + nx_mlc_priority_videofourth = 3ul +}; + +enum nx_mlc_rgbfmt { + nx_mlc_rgbfmt_r5g6b5 = 0x44320000ul, + nx_mlc_rgbfmt_b5g6r5 = 0xc4320000ul, + nx_mlc_rgbfmt_x1r5g5b5 = 0x43420000ul, + nx_mlc_rgbfmt_x1b5g5r5 = 0xc3420000ul, + nx_mlc_rgbfmt_x4r4g4b4 = 0x42110000ul, + nx_mlc_rgbfmt_x4b4g4r4 = 0xc2110000ul, + nx_mlc_rgbfmt_x8r3g3b2 = 0x41200000ul, + nx_mlc_rgbfmt_x8b3g3r2 = 0xc1200000ul, + nx_mlc_rgbfmt_a1r5g5b5 = 0x33420000ul, + nx_mlc_rgbfmt_a1b5g5r5 = 0xb3420000ul, + nx_mlc_rgbfmt_a4r4g4b4 = 0x22110000ul, + nx_mlc_rgbfmt_a4b4g4r4 = 0xa2110000ul, + nx_mlc_rgbfmt_a8r3g3b2 = 0x11200000ul, + nx_mlc_rgbfmt_a8b3g3r2 = 0x91200000ul, + nx_mlc_rgbfmt_r8g8b8 = 0x46530000ul, + nx_mlc_rgbfmt_b8g8r8 = 0xc6530000ul, + nx_mlc_rgbfmt_x8r8g8b8 = 0x46530000ul, + nx_mlc_rgbfmt_x8b8g8r8 = 0xc6530000ul, + nx_mlc_rgbfmt_a8r8g8b8 = 0x06530000ul, + nx_mlc_rgbfmt_a8b8g8r8 = 0x86530000ul +}; + +enum nx_mlc_yuvfmt { + nx_mlc_yuvfmt_420 = 0ul << 16, + nx_mlc_yuvfmt_422 = 1ul << 16, + nx_mlc_yuvfmt_444 = 3ul << 16, + nx_mlc_yuvfmt_yuyv = 2ul << 16, + nx_mlc_yuvfmt_422_cbcr = 4ul << 16, + nx_mlc_yuvfmt_420_cbcr = 5ul << 16, +}; + +#ifdef __arm +#pragma diag_default 66 +#endif + +int nx_mlc_initialize(void); +u32 nx_mlc_get_number_of_module(void); +u32 nx_mlc_get_physical_address(u32 module_index); +u32 nx_mlc_get_size_of_register_set(void); +void nx_mlc_set_base_address(u32 module_index, void *base_address); +void *nx_mlc_get_base_address(u32 module_index); +int nx_mlc_open_module(u32 module_index); +int nx_mlc_close_module(u32 module_index); +int nx_mlc_check_busy(u32 module_index); +int nx_mlc_can_power_down(u32 module_index); +void nx_mlc_set_clock_pclk_mode(u32 module_index, enum nx_pclkmode mode); +enum nx_pclkmode nx_mlc_get_clock_pclk_mode(u32 module_index); +void nx_mlc_set_clock_bclk_mode(u32 module_index, enum nx_bclkmode mode); +enum nx_bclkmode nx_mlc_get_clock_bclk_mode(u32 module_index); + +void nx_mlc_set_top_power_mode(u32 module_index, int bpower); +int nx_mlc_get_top_power_mode(u32 module_index); +void nx_mlc_set_top_sleep_mode(u32 module_index, int bsleep); +int nx_mlc_get_top_sleep_mode(u32 module_index); +void nx_mlc_set_top_dirty_flag(u32 module_index); +int nx_mlc_get_top_dirty_flag(u32 module_index); +void nx_mlc_set_mlc_enable(u32 module_index, int benb); +int nx_mlc_get_mlc_enable(u32 module_index); +void nx_mlc_set_field_enable(u32 module_index, int benb); +int nx_mlc_get_field_enable(u32 module_index); +void nx_mlc_set_layer_priority(u32 module_index, + enum nx_mlc_priority priority); +void nx_mlc_set_screen_size(u32 module_index, u32 width, u32 height); +void nx_mlc_get_screen_size(u32 module_index, u32 *pwidth, + u32 *pheight); +void nx_mlc_set_background(u32 module_index, u32 color); + +void nx_mlc_set_dirty_flag(u32 module_index, u32 layer); +int nx_mlc_get_dirty_flag(u32 module_index, u32 layer); +void nx_mlc_set_layer_enable(u32 module_index, u32 layer, int benb); +int nx_mlc_get_layer_enable(u32 module_index, u32 layer); +void nx_mlc_set_lock_size(u32 module_index, u32 layer, u32 locksize); +void nx_mlc_set_alpha_blending(u32 module_index, u32 layer, int benb, + u32 alpha); +void nx_mlc_set_transparency(u32 module_index, u32 layer, int benb, + u32 color); +void nx_mlc_set_color_inversion(u32 module_index, u32 layer, int benb, + u32 color); +u32 nx_mlc_get_extended_color(u32 module_index, u32 color, + enum nx_mlc_rgbfmt format); +void nx_mlc_set_format_rgb(u32 module_index, u32 layer, + enum nx_mlc_rgbfmt format); +void nx_mlc_set_format_yuv(u32 module_index, enum nx_mlc_yuvfmt format); +void nx_mlc_set_position(u32 module_index, u32 layer, s32 sx, + s32 sy, s32 ex, s32 ey); +void nx_mlc_set_dither_enable_when_using_gamma(u32 module_index, + int benable); +int nx_mlc_get_dither_enable_when_using_gamma(u32 module_index); +void nx_mlc_set_gamma_priority(u32 module_index, int bvideolayer); +int nx_mlc_get_gamma_priority(u32 module_index); + +void nx_mlc_set_rgblayer_invalid_position(u32 module_index, u32 layer, + u32 region, s32 sx, + s32 sy, s32 ex, + s32 ey, int benb); +void nx_mlc_set_rgblayer_stride(u32 module_index, u32 layer, + s32 hstride, s32 vstride); +void nx_mlc_set_rgblayer_address(u32 module_index, u32 layer, u32 addr); +void nx_mlc_set_rgblayer_gama_table_power_mode(u32 module_index, + int bred, int bgreen, + int bblue); +void nx_mlc_get_rgblayer_gama_table_power_mode(u32 module_index, + int *pbred, int *pbgreen, + int *pbblue); +void nx_mlc_set_rgblayer_gama_table_sleep_mode(u32 module_index, + int bred, int bgreen, + int bblue); +void nx_mlc_get_rgblayer_gama_table_sleep_mode(u32 module_index, + int *pbred, int *pbgreen, + int *pbblue); +void nx_mlc_set_rgblayer_rgamma_table(u32 module_index, u32 dwaddress, + u32 dwdata); +void nx_mlc_set_rgblayer_ggamma_table(u32 module_index, u32 dwaddress, + u32 dwdata); +void nx_mlc_set_rgblayer_bgamma_table(u32 module_index, u32 dwaddress, + u32 dwdata); +void nx_mlc_set_rgblayer_gamma_enable(u32 module_index, int benable); +int nx_mlc_get_rgblayer_gamma_enable(u32 module_index); + +void nx_mlc_set_video_layer_stride(u32 module_index, s32 lu_stride, + s32 cb_stride, s32 cr_stride); +void nx_mlc_set_video_layer_address(u32 module_index, u32 lu_addr, + u32 cb_addr, u32 cr_addr); +void nx_mlc_set_video_layer_address_yuyv(u32 module_index, u32 addr, + s32 stride); +void nx_mlc_set_video_layer_scale_factor(u32 module_index, u32 hscale, + u32 vscale, int bhlumaenb, + int bhchromaenb, int bvlumaenb, + int bvchromaenb); +void nx_mlc_set_video_layer_scale_filter(u32 module_index, int bhlumaenb, + int bhchromaenb, int bvlumaenb, + int bvchromaenb); +void nx_mlc_get_video_layer_scale_filter(u32 module_index, + int *bhlumaenb, + int *bhchromaenb, + int *bvlumaenb, + int *bvchromaenb); +void nx_mlc_set_video_layer_scale(u32 module_index, u32 sw, u32 sh, + u32 dw, u32 dh, int bhlumaenb, + int bhchromaenb, int bvlumaenb, + int bvchromaenb); +void nx_mlc_set_video_layer_luma_enhance(u32 module_index, u32 contrast, + s32 brightness); +void nx_mlc_set_video_layer_chroma_enhance(u32 module_index, + u32 quadrant, s32 cb_a, + s32 cb_b, s32 cr_a, + s32 cr_b); +void nx_mlc_set_video_layer_line_buffer_power_mode(u32 module_index, + int benable); +int nx_mlc_get_video_layer_line_buffer_power_mode(u32 module_index); +void nx_mlc_set_video_layer_line_buffer_sleep_mode(u32 module_index, + int benable); +int nx_mlc_get_video_layer_line_buffer_sleep_mode(u32 module_index); +void nx_mlc_set_video_layer_gamma_enable(u32 module_index, int benable); +int nx_mlc_get_video_layer_gamma_enable(u32 module_index); + +void nx_mlc_set_gamma_table_poweroff(u32 module_index, int enb); + +enum mlc_rgbfmt { + rgbfmt_r5g6b5 = 0, + rgbfmt_x1r5g5b5 = 1, + rgbfmt_x4r4g4b4 = 2, + rgbfmt_x8r3g3b2 = 3, + rgbfmt_x8l8 = 4, + rgbfmt_l16 = 5, + rgbfmt_a1r5g5b5 = 6, + rgbfmt_a4r4g4b4 = 7, + rgbfmt_a8r3g3b2 = 8, + rgbfmt_a8l8 = 9, + rgbfmt_r8g8b8 = 10, + rgbfmt_x8r8g8b8 = 11, + rgbfmt_a8r8g8b8 = 12, + rgbfmt_g8r8_g8b8 = 13, + rgbfmt_r8g8_b8g8 = 14, + rgbfmt_b5g6r5 = 15, + rgbfmt_x1b5g5r5 = 16, + rgbfmt_x4b4g4r4 = 17, + rgbfmt_x8b3g3r2 = 18, + rgbfmt_a1b5g5r5 = 19, + rgbfmt_a4b4g4r4 = 20, + rgbfmt_a8b3g3r2 = 21, + rgbfmt_b8g8r8 = 22, + rgbfmt_x8b8g8r8 = 23, + rgbfmt_a8b8g8r8 = 24, + rgbfmt_g8b8_g8r8 = 25, + rgbfmt_b8g8_r8g8 = 26, + rgbfmt_pataletb = 27 +}; + +enum latyername { + topmlc = 0, + rgb0 = 1, + rgb1 = 2, + rgb2 = 3, + video = 4 +}; + +enum srammode { + poweroff = 0, + sleepmode = 2, + run = 3 +}; + +enum locksizesel { + locksize_4 = 0, + locksize_8 = 1, + locksize_16 = 2 +}; + +enum g3daddrchangeallowed { + prim = 0, + secon = 1, + primorsecon = 2, + primandsecon = 3 +}; + +void nx_mlc_set_mlctop_control_parameter(u32 module_index, + int field_enable, int mlcenable, + u8 priority, + enum g3daddrchangeallowed + g3daddr_change_allowed); +void nx_mlc_set_rgb0layer_control_parameter(u32 module_index, + int layer_enable, + int grp3denable, + int tp_enable, + u32 transparency_color, + int inv_enable, + u32 inverse_color, + int blend_enable, + u8 alpha_value, + enum mlc_rgbfmt rbgformat, + enum locksizesel + lock_size_select); + +u32 nx_mlc_get_rgbformat(enum mlc_rgbfmt rbgformat); +void nx_mlc_set_rgb1layer_control_parameter(u32 module_index, + int layer_enable, + int grp3denable, + int tp_enable, + u32 transparency_color, + int inv_enable, + u32 inverse_color, + int blend_enable, + u8 alpha_value, + enum mlc_rgbfmt rbgformat, + enum locksizesel + lock_size_select); + +void nx_mlc_set_rgb2layer_control_parameter(u32 module_index, + int layer_enable, + int grp3denable, + int tp_enable, + u32 transparency_color, + int inv_enable, + u32 inverse_color, + int blend_enable, + u8 alpha_value, + enum mlc_rgbfmt rbgformat, + enum locksizesel + lock_size_select); + +void nx_mlc_set_video_layer_control_parameter(u32 module_index, + int layer_enable, + int tp_enable, + u32 transparency_color, + int inv_enable, + u32 inverse_color, + int blend_enable, + u8 alpha_value, + enum nx_mlc_yuvfmt + yuvformat); + +void nx_mlc_set_srammode(u32 module_index, enum latyername layer_name, + enum srammode sram_mode); + +void nx_mlc_set_layer_reg_finish(u32 module_index, + enum latyername layer_name); + +void nx_mlc_set_video_layer_coordinate(u32 module_index, + int vfilterenable, + int hfilterenable, + int vfilterenable_c, + int hfilterenable_c, + u16 video_layer_with, + u16 video_layer_height, + s16 left, s16 right, + s16 top, s16 bottom); + +void nx_mlc_set_video_layer_filter_scale(u32 module_index, u32 hscale, + u32 vscale); +void nx_mlcsetgammasrammode(u32 module_index, enum srammode sram_mode); +void nx_mlc_set_gamma_control_parameter(u32 module_index, + int rgbgammaenb, int yuvgammaenb, + int yuvalphaarray, + int dither_enb); + +void nx_mlc_set_layer_alpha256(u32 module_index, u32 layer, u32 alpha); +int nx_mlc_is_under_flow(u32 module_index); + +struct nx_mlc_gamma_table_parameter { + u32 r_table[256]; + u32 g_table[256]; + u32 b_table[256]; + u32 ditherenb; + u32 alphaselect; + u32 yuvgammaenb; + u32 rgbgammaenb; + u32 allgammaenb; +}; + +void nx_mlc_set_gamma_table(u32 module_index, int enb, + struct nx_mlc_gamma_table_parameter *p_gammatable); +void nx_mlc_get_rgblayer_stride(u32 module_index, u32 layer, + s32 *hstride, s32 *vstride); +void nx_mlc_get_rgblayer_address(u32 module_index, u32 layer, + u32 *phys_address); +void nx_mlc_get_position(u32 module_index, u32 layer, int *left, + int *top, int *right, int *bottom); +void nx_mlc_get_video_layer_address_yuyv(u32 module_index, u32 *address, + u32 *stride); +void nx_mlc_get_video_layer_address(u32 module_index, u32 *lu_address, + u32 *cb_address, u32 *cr_address); +void nx_mlc_get_video_layer_stride(u32 module_index, u32 *lu_stride, + u32 *cb_stride, u32 *cr_stride); +void nx_mlc_get_video_layer_stride(u32 module_index, u32 *lu_stride, + u32 *cb_stride, u32 *cr_stride); +void nx_mlc_get_video_position(u32 module_index, int *left, int *top, + int *right, int *bottom); + +#endif |