From 1ac182d2029ee16d127e57037bdbc206f07d43f5 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sat, 29 Jun 2013 13:46:13 +0200 Subject: [PATCH 01/30] copy-pasted some driver code from the internet. Does not compile yet. --- arch/arm/plat-samsung/devs.c | 7 + drivers/media/platform/s5p-tv/Kconfig | 9 + drivers/media/platform/s5p-tv/Makefile | 3 +- drivers/media/platform/s5p-tv/hw_if/cec.c | 239 +++++++ drivers/media/platform/s5p-tv/hw_if/hw_if.h | 651 ++++++++++++++++++++ drivers/media/platform/s5p-tv/s5p-cec.c | 371 +++++++++++ 6 files changed, 1279 insertions(+), 1 deletion(-) create mode 100644 drivers/media/platform/s5p-tv/hw_if/cec.c create mode 100644 drivers/media/platform/s5p-tv/hw_if/hw_if.h create mode 100644 drivers/media/platform/s5p-tv/s5p-cec.c diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index 82e30674093a8d..099173ed43f79d 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c @@ -1357,6 +1357,13 @@ struct platform_device s5p_device_hdmi = { .resource = s5p_hdmi_resources, }; +struct platform_device s5p_device_hdmi_cec = { + .name = "s5p-cec", + .id = -1, + .num_resources = 0; //ARRAY_SIZE(s5p_hdmi_resources), + .resource = s5p_hdmi_resources, +}; + static struct resource s5p_sdo_resources[] = { [0] = DEFINE_RES_MEM(S5P_PA_SDO, SZ_64K), [1] = DEFINE_RES_IRQ(IRQ_SDO), diff --git a/drivers/media/platform/s5p-tv/Kconfig b/drivers/media/platform/s5p-tv/Kconfig index 9f2fbebc7ed19c..9d67f04f8bd15c 100644 --- a/drivers/media/platform/s5p-tv/Kconfig +++ b/drivers/media/platform/s5p-tv/Kconfig @@ -36,6 +36,15 @@ config VIDEO_SAMSUNG_S5P_HDMI_DEBUG help Enables debugging for HDMI driver. +config VIDEO_SAMSUNG_S5P_HDMI_CEC + tristate "Enable CEC support for HDMI Driver" + depends on VIDEO_SAMSUNG_S5P_HDMI + default y + help + Enables CEC over the HDMI driver. + CEC enables tv-control, and reception of tv-remote + control commands over the HDMI interface + config VIDEO_SAMSUNG_S5P_HDMIPHY tristate "Samsung HDMIPHY Driver" depends on VIDEO_DEV && VIDEO_V4L2 && I2C diff --git a/drivers/media/platform/s5p-tv/Makefile b/drivers/media/platform/s5p-tv/Makefile index da2f98fe24abf9..08137955d63657 100644 --- a/drivers/media/platform/s5p-tv/Makefile +++ b/drivers/media/platform/s5p-tv/Makefile @@ -13,9 +13,10 @@ s5p-sii9234-y += sii9234_drv.o obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMI) += s5p-hdmi.o s5p-hdmi-$(CONFIG_CPU_EXYNOS4210) += hdmi_drv.o s5p-hdmi-$(CONFIG_SOC_EXYNOS4412) += hdmi_v14_drv.o +# obj-$(VIDEO_SAMSUNG_S5P_HDMI_CEC) += s5p-cec.o +s5p-cec-$(VIDEO_SAMSUNG_S5P_HDMI_CEC) += s5p-cec.o obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SDO) += s5p-sdo.o s5p-sdo-y += sdo_drv.o obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MIXER) += s5p-mixer.o s5p-mixer-y += mixer_drv.o mixer_video.o mixer_reg.o mixer_grp_layer.o mixer_vp_layer.o - diff --git a/drivers/media/platform/s5p-tv/hw_if/cec.c b/drivers/media/platform/s5p-tv/hw_if/cec.c new file mode 100644 index 00000000000000..dbff584203e8a2 --- /dev/null +++ b/drivers/media/platform/s5p-tv/hw_if/cec.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * CEC for Samsung S5P TVOUT driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include + +#include +#include +#include + +#include "../s5p_tvout_common_lib.h" +#include "hw_if.h" + +#define S5P_HDMI_FIN 24000000 +#define CEC_DIV_RATIO 320000 + +#define CEC_MESSAGE_BROADCAST_MASK 0x0F +#define CEC_MESSAGE_BROADCAST 0x0F +#define CEC_FILTER_THRESHOLD 0x15 + +static struct resource *cec_mem; +void __iomem *cec_base; + +struct cec_rx_struct cec_rx_struct; +struct cec_tx_struct cec_tx_struct; + +void s5p_cec_set_divider(void) +{ + u32 div_ratio, reg, div_val; + + div_ratio = (S5P_HDMI_FIN / CEC_DIV_RATIO) - 1; + + reg = readl(S5P_HDMI_PHY_CONTROL); + reg = (reg & ~(0x3FF << 16)) | (div_ratio << 16); + + writel(reg, S5P_HDMI_PHY_CONTROL); + + div_val = (CEC_DIV_RATIO * 0.00005) - 1; + + writeb(0x0, cec_base + S5P_CEC_DIVISOR_3); + writeb(0x0, cec_base + S5P_CEC_DIVISOR_2); + writeb(0x0, cec_base + S5P_CEC_DIVISOR_1); + writeb(div_val, cec_base + S5P_CEC_DIVISOR_0); +} + +void s5p_cec_enable_rx(void) +{ + u8 reg; + + reg = readb(cec_base + S5P_CEC_RX_CTRL); + reg |= S5P_CEC_RX_CTRL_ENABLE; + writeb(reg, cec_base + S5P_CEC_RX_CTRL); +} + +void s5p_cec_mask_rx_interrupts(void) +{ + u8 reg; + + reg = readb(cec_base + S5P_CEC_IRQ_MASK); + reg |= S5P_CEC_IRQ_RX_DONE; + reg |= S5P_CEC_IRQ_RX_ERROR; + writeb(reg, cec_base + S5P_CEC_IRQ_MASK); +} + +void s5p_cec_unmask_rx_interrupts(void) +{ + u8 reg; + + reg = readb(cec_base + S5P_CEC_IRQ_MASK); + reg &= ~S5P_CEC_IRQ_RX_DONE; + reg &= ~S5P_CEC_IRQ_RX_ERROR; + writeb(reg, cec_base + S5P_CEC_IRQ_MASK); +} + +void s5p_cec_mask_tx_interrupts(void) +{ + u8 reg; + + reg = readb(cec_base + S5P_CEC_IRQ_MASK); + reg |= S5P_CEC_IRQ_TX_DONE; + reg |= S5P_CEC_IRQ_TX_ERROR; + writeb(reg, cec_base + S5P_CEC_IRQ_MASK); +} + +void s5p_cec_unmask_tx_interrupts(void) +{ + u8 reg; + + reg = readb(cec_base + S5P_CEC_IRQ_MASK); + reg &= ~S5P_CEC_IRQ_TX_DONE; + reg &= ~S5P_CEC_IRQ_TX_ERROR; + writeb(reg, cec_base + S5P_CEC_IRQ_MASK); +} + +void s5p_cec_tx_reset(void) +{ + writeb(S5P_CEC_TX_CTRL_RESET, cec_base + S5P_CEC_TX_CTRL); +} + +void s5p_cec_rx_reset(void) +{ + writeb(S5P_CEC_RX_CTRL_RESET, cec_base + S5P_CEC_RX_CTRL); +} + +void s5p_cec_reset(void) +{ + s5p_cec_rx_reset(); + s5p_cec_tx_reset(); +} + +void s5p_cec_threshold(void) +{ + writeb(CEC_FILTER_THRESHOLD, cec_base + S5P_CEC_RX_FILTER_TH); + writeb(0, cec_base + S5P_CEC_RX_FILTER_CTRL); +} + +void s5p_cec_set_tx_state(enum cec_state state) +{ + atomic_set(&cec_tx_struct.state, state); +} + +void s5p_cec_set_rx_state(enum cec_state state) +{ + atomic_set(&cec_rx_struct.state, state); +} + +void s5p_cec_copy_packet(char *data, size_t count) +{ + int i = 0; + u8 reg; + + while (i < count) { + writeb(data[i], cec_base + (S5P_CEC_TX_BUFF0 + (i * 4))); + i++; + } + + writeb(count, cec_base + S5P_CEC_TX_BYTES); + s5p_cec_set_tx_state(STATE_TX); + reg = readb(cec_base + S5P_CEC_TX_CTRL); + reg |= S5P_CEC_TX_CTRL_START; + + if ((data[0] & CEC_MESSAGE_BROADCAST_MASK) == CEC_MESSAGE_BROADCAST) + reg |= S5P_CEC_TX_CTRL_BCAST; + else + reg &= ~S5P_CEC_TX_CTRL_BCAST; + + reg |= 0x50; + writeb(reg, cec_base + S5P_CEC_TX_CTRL); +} + +void s5p_cec_set_addr(u32 addr) +{ + writeb(addr & 0x0F, cec_base + S5P_CEC_LOGIC_ADDR); +} + +u32 s5p_cec_get_status(void) +{ + u32 status = 0; + + status = readb(cec_base + S5P_CEC_STATUS_0); + status |= readb(cec_base + S5P_CEC_STATUS_1) << 8; + status |= readb(cec_base + S5P_CEC_STATUS_2) << 16; + status |= readb(cec_base + S5P_CEC_STATUS_3) << 24; + + return status; +} + +void s5p_clr_pending_tx(void) +{ + writeb(S5P_CEC_IRQ_TX_DONE | S5P_CEC_IRQ_TX_ERROR, + cec_base + S5P_CEC_IRQ_CLEAR); +} + +void s5p_clr_pending_rx(void) +{ + writeb(S5P_CEC_IRQ_RX_DONE | S5P_CEC_IRQ_RX_ERROR, + cec_base + S5P_CEC_IRQ_CLEAR); +} + +void s5p_cec_get_rx_buf(u32 size, u8 *buffer) +{ + u32 i = 0; + + while (i < size) { + buffer[i] = readb(cec_base + S5P_CEC_RX_BUFF0 + (i * 4)); + i++; + } +} + +void __init s5p_cec_mem_probe(struct platform_device *pdev) +{ + struct resource *res; + size_t size = 0; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, + "failed to get memory region resource for cec\n"); + ret = -ENOENT; + } else + size = resource_size(res); + + cec_mem = request_mem_region(res->start, size, pdev->name); + if (cec_mem == NULL) { + dev_err(&pdev->dev, + "failed to get memory region for cec\n"); + ret = -ENOENT; + } + + cec_base = ioremap(res->start, size); + if (cec_base == NULL) { + dev_err(&pdev->dev, + "failed to ioremap address region for cec\n"); + ret = -ENOENT; + } +} + +int __init s5p_cec_mem_release(struct platform_device *pdev) +{ + iounmap(cec_base); + if (cec_mem != NULL) { + if (release_resource(cec_mem)) + dev_err(&pdev->dev, "can't remove tvout drv !!\n"); + + kfree(cec_mem); + + cec_mem = NULL; + } + return 0; +} diff --git a/drivers/media/platform/s5p-tv/hw_if/hw_if.h b/drivers/media/platform/s5p-tv/hw_if/hw_if.h new file mode 100644 index 00000000000000..ac461666106e1b --- /dev/null +++ b/drivers/media/platform/s5p-tv/hw_if/hw_if.h @@ -0,0 +1,651 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Header file for interface of Samsung TVOUT-related hardware + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __S5P_TVOUT_HW_IF_H_ +#define __S5P_TVOUT_HW_IF_H_ __FILE__ + +/* + * This file includes declarations for external functions of + * Samsung TVOUT-related hardware. So only external functions + * to be used by higher layer must exist in this file. + * + * Higher layer must use only the declarations included in this file. + */ + +#include +#include + +#include "../s5p_tvout_common_lib.h" + +/* Common */ + +enum s5p_tvout_endian { + TVOUT_LITTLE_ENDIAN = 0, + TVOUT_BIG_ENDIAN = 1 +}; + +/* for MIXER */ + +enum s5p_mixer_layer { + MIXER_VIDEO_LAYER = 2, + MIXER_GPR0_LAYER = 0, + MIXER_GPR1_LAYER = 1 +}; + +enum s5p_mixer_bg_color_num { + MIXER_BG_COLOR_0 = 0, + MIXER_BG_COLOR_1 = 1, + MIXER_BG_COLOR_2 = 2 +}; + +enum s5p_mixer_color_fmt { + MIXER_RGB565 = 4, + MIXER_RGB1555 = 5, + MIXER_RGB4444 = 6, + MIXER_RGB8888 = 7 +}; + +enum s5p_mixer_csc_type { + MIXER_CSC_601_LR, + MIXER_CSC_601_FR, + MIXER_CSC_709_LR, + MIXER_CSC_709_FR +}; + +enum s5p_mixer_rgb { + MIXER_RGB601_0_255, + MIXER_RGB601_16_235, + MIXER_RGB709_0_255, + MIXER_RGB709_16_235 +}; + +enum s5p_mixer_out_type { + MIXER_YUV444, + MIXER_RGB888 +}; + +extern int s5p_mixer_set_show(enum s5p_mixer_layer layer, bool show); +extern int s5p_mixer_set_priority(enum s5p_mixer_layer layer, u32 priority); +extern void s5p_mixer_set_pre_mul_mode(enum s5p_mixer_layer layer, bool enable); +extern int s5p_mixer_set_pixel_blend(enum s5p_mixer_layer layer, bool enable); +extern int s5p_mixer_set_layer_blend(enum s5p_mixer_layer layer, bool enable); +extern int s5p_mixer_set_alpha(enum s5p_mixer_layer layer, u32 alpha); +extern int s5p_mixer_set_grp_base_address(enum s5p_mixer_layer layer, + u32 baseaddr); +extern int s5p_mixer_set_grp_layer_dst_pos(enum s5p_mixer_layer layer, + u32 dst_offs_x, u32 dst_offs_y); +extern int s5p_mixer_set_grp_layer_src_pos(enum s5p_mixer_layer layer, + u32 span, u32 width, u32 height, + u32 src_offs_x, u32 src_offs_y); +extern void s5p_mixer_set_bg_color(enum s5p_mixer_bg_color_num colornum, + u32 color_y, u32 color_cb, u32 color_cr); +extern void s5p_mixer_init_status_reg(enum s5p_mixer_burst_mode burst, + enum s5p_tvout_endian endian); +extern int s5p_mixer_init_display_mode(enum s5p_tvout_disp_mode mode, + enum s5p_tvout_o_mode output_mode); +extern void s5p_mixer_scaling(enum s5p_mixer_layer layer, + struct s5ptvfb_user_scaling scaling); +extern void s5p_mixer_set_color_format(enum s5p_mixer_layer layer, + enum s5p_mixer_color_fmt format); +extern void s5p_mixer_set_chroma_key(enum s5p_mixer_layer layer, + bool enabled, u32 key); +extern void s5p_mixer_init_bg_dither_enable(bool cr_dither_enable, + bool cdither_enable, + bool y_dither_enable); +extern void s5p_mixer_init_csc_coef_default(enum s5p_mixer_csc_type csc_type); +extern void s5p_mixer_start(void); +extern void s5p_mixer_stop(void); +extern void s5p_mixer_set_underflow_int_enable(enum s5p_mixer_layer layer, + bool en); +extern void s5p_mixer_set_vsync_interrupt(bool); +extern void s5p_mixer_clear_pend_all(void); +extern irqreturn_t s5p_mixer_irq(int irq, void *dev_id); +extern void s5p_mixer_init(void __iomem *addr); + +/* for HDMI */ + +#define HDMI_MASK_8(x) ((x) & 0xFF) +#define HDMI_MASK_16(x) (((x) >> 8) & 0xFF) +#define HDMI_MASK_24(x) (((x) >> 16) & 0xFF) +#define HDMI_MASK_32(x) (((x) >> 24) & 0xFF) + +#define hdmi_write_16(x, y) \ + do { \ + writeb(HDMI_MASK_8(x), y); \ + writeb(HDMI_MASK_16(x), y + 4); \ + } while (0); + +#define hdmi_write_24(x, y) \ + do { \ + writeb(HDMI_MASK_8(x), y); \ + writeb(HDMI_MASK_16(x), y + 4); \ + writeb(HDMI_MASK_24(x), y + 8); \ + } while (0); + +#define hdmi_write_32(x, y) \ + do { \ + writeb(HDMI_MASK_8(x), y); \ + writeb(HDMI_MASK_16(x), y + 4); \ + writeb(HDMI_MASK_24(x), y + 8); \ + writeb(HDMI_MASK_32(x), y + 12); \ + } while (0); + +#define hdmi_write_l(buff, base, start, count) \ + do { \ + u8 *ptr = buff; \ + int i = 0; \ + int a = start; \ + do { \ + writeb(ptr[i], base + a); \ + a += 4; \ + i++; \ + } while (i <= (count - 1)); \ + } while (0); + +#define hdmi_read_l(buff, base, start, count) \ + do { \ + u8 *ptr = buff; \ + int i = 0; \ + int a = start; \ + do { \ + ptr[i] = readb(base + a); \ + a += 4; \ + i++; \ + } while (i <= (count - 1)); \ + } while (0); + +#define hdmi_bit_set(en, reg, val) \ + do { \ + if (en) \ + reg |= val; \ + else \ + reg &= ~val; \ + } while (0); + +enum s5p_hdmi_transmit { + HDMI_DO_NOT_TANS, + HDMI_TRANS_ONCE, + HDMI_TRANS_EVERY_SYNC, +}; + +enum s5p_tvout_audio_codec_type { + PCM = 1, + AC3, + MP3, + WMA +}; + +enum s5p_hdmi_infoframe_type { + HDMI_VSI_INFO = 0x81, + HDMI_AVI_INFO, + HDMI_SPD_INFO, + HDMI_AUI_INFO, + HDMI_MPG_INFO, +}; + +enum s5p_hdmi_color_depth { + HDMI_CD_48, + HDMI_CD_36, + HDMI_CD_30, + HDMI_CD_24 +}; + +enum s5p_hdmi_interrrupt { + HDMI_IRQ_PIN_POLAR_CTL = 7, + HDMI_IRQ_GLOBAL = 6, + HDMI_IRQ_I2S = 5, + HDMI_IRQ_CEC = 4, + HDMI_IRQ_HPD_PLUG = 3, + HDMI_IRQ_HPD_UNPLUG = 2, + HDMI_IRQ_SPDIF = 1, + HDMI_IRQ_HDCP = 0 +}; + +enum phy_freq { + ePHY_FREQ_25_200, + ePHY_FREQ_25_175, + ePHY_FREQ_27, + ePHY_FREQ_27_027, + ePHY_FREQ_54, + ePHY_FREQ_54_054, + ePHY_FREQ_74_250, + ePHY_FREQ_74_176, + ePHY_FREQ_148_500, + ePHY_FREQ_148_352, + ePHY_FREQ_108_108, + ePHY_FREQ_72, + ePHY_FREQ_25, + ePHY_FREQ_65, + ePHY_FREQ_108, + ePHY_FREQ_162 +}; + +struct s5p_hdmi_infoframe { + enum s5p_hdmi_infoframe_type type; + u8 version; + u8 length; +}; + +struct s5p_hdmi_o_trans { + enum s5p_hdmi_transmit avi; + enum s5p_hdmi_transmit mpg; + enum s5p_hdmi_transmit spd; + enum s5p_hdmi_transmit gcp; + enum s5p_hdmi_transmit gmp; + enum s5p_hdmi_transmit isrc; + enum s5p_hdmi_transmit acp; + enum s5p_hdmi_transmit aui; + enum s5p_hdmi_transmit acr; +}; + +struct s5p_hdmi_o_reg { + u8 pxl_fmt; + u8 preemble; + u8 mode; + u8 pxl_limit; + u8 dvi; +}; + +struct s5p_hdmi_v_frame { + u8 vic; + u8 vic_16_9; + u8 repetition; + u8 polarity; + u8 i_p; + + u16 h_active; + u16 v_active; + + u16 h_total; + u16 h_blank; + + u16 v_total; + u16 v_blank; + + enum phy_freq pixel_clock; +}; + +struct s5p_hdmi_tg_sync { + u16 begin; + u16 end; +}; + +struct s5p_hdmi_v_format { + struct s5p_hdmi_v_frame frame; + + struct s5p_hdmi_tg_sync h_sync; + struct s5p_hdmi_tg_sync v_sync_top; + struct s5p_hdmi_tg_sync v_sync_bottom; + struct s5p_hdmi_tg_sync v_sync_h_pos; + + struct s5p_hdmi_tg_sync v_blank_f; + + u8 mhl_hsync; + u8 mhl_vsync; +}; + +extern int s5p_hdmi_phy_power(bool on); +extern s32 s5p_hdmi_phy_config(enum phy_freq freq, + enum s5p_hdmi_color_depth cd); + +extern void s5p_hdmi_set_gcp(enum s5p_hdmi_color_depth depth, u8 *gcp); +extern void s5p_hdmi_reg_acr(u8 *acr); +extern void s5p_hdmi_reg_asp(u8 *asp); +extern void s5p_hdmi_reg_gcp(u8 i_p, u8 *gcp); +extern void s5p_hdmi_reg_acp(u8 *header, u8 *acp); +extern void s5p_hdmi_reg_isrc(u8 *isrc1, u8 *isrc2); +extern void s5p_hdmi_reg_gmp(u8 *gmp); +extern void s5p_hdmi_reg_infoframe(struct s5p_hdmi_infoframe *info, u8 *data); +extern void s5p_hdmi_reg_tg(struct s5p_hdmi_v_frame *frame); +extern void s5p_hdmi_reg_v_timing(struct s5p_hdmi_v_format *v); +extern void s5p_hdmi_reg_bluescreen_clr(u8 cb_b, u8 y_g, u8 cr_r); +extern void s5p_hdmi_reg_bluescreen(bool en); +extern void s5p_hdmi_reg_clr_range(u8 y_min, u8 y_max, u8 c_min, u8 c_max); +extern void s5p_hdmi_reg_tg_cmd(bool time, bool bt656, bool tg); +extern void s5p_hdmi_reg_enable(bool en); +extern u8 s5p_hdmi_reg_intc_status(void); +extern u8 s5p_hdmi_reg_intc_get_enabled(void); +extern void s5p_hdmi_reg_intc_clear_pending(enum s5p_hdmi_interrrupt intr); +extern void s5p_hdmi_reg_sw_hpd_enable(bool enable); +extern void s5p_hdmi_reg_set_hpd_onoff(bool on_off); +extern u8 s5p_hdmi_reg_get_hpd_status(void); +extern void s5p_hdmi_reg_hpd_gen(void); +extern int s5p_hdmi_reg_intc_set_isr(irqreturn_t (*isr)(int, void *), u8 num); +extern void s5p_hdmi_reg_intc_enable(enum s5p_hdmi_interrrupt intr, u8 en); +extern void s5p_hdmi_reg_audio_enable(u8 en); +extern int s5p_hdmi_audio_init(enum s5p_tvout_audio_codec_type audio_codec, + u32 sample_rate, u32 bits, u32 frame_size_code); +extern irqreturn_t s5p_hdmi_irq(int irq, void *dev_id); +extern void s5p_hdmi_init(void __iomem *hdmi_addr, + void __iomem *hdmi_phy_addr); +extern void s5p_hdmi_reg_output(struct s5p_hdmi_o_reg *reg); +extern void s5p_hdmi_reg_packet_trans(struct s5p_hdmi_o_trans *trans); +extern void s5p_hdmi_reg_mute(bool en); + +extern void __iomem *hdmi_base; + +/* for SDO */ + +enum s5p_sdo_level { + SDO_LEVEL_0IRE, + SDO_LEVEL_75IRE +}; + +enum s5p_sdo_vsync_ratio { + SDO_VTOS_RATIO_10_4, + SDO_VTOS_RATIO_7_3 +}; + +enum s5p_sdo_order { + SDO_O_ORDER_COMPONENT_RGB_PRYPB, + SDO_O_ORDER_COMPONENT_RBG_PRPBY, + SDO_O_ORDER_COMPONENT_BGR_PBYPR, + SDO_O_ORDER_COMPONENT_BRG_PBPRY, + SDO_O_ORDER_COMPONENT_GRB_YPRPB, + SDO_O_ORDER_COMPONENT_GBR_YPBPR, + SDO_O_ORDER_COMPOSITE_CVBS_Y_C, + SDO_O_ORDER_COMPOSITE_CVBS_C_Y, + SDO_O_ORDER_COMPOSITE_Y_C_CVBS, + SDO_O_ORDER_COMPOSITE_Y_CVBS_C, + SDO_O_ORDER_COMPOSITE_C_CVBS_Y, + SDO_O_ORDER_COMPOSITE_C_Y_CVBS +}; + +enum s5p_sdo_sync_sig_pin { + SDO_SYNC_SIG_NO, + SDO_SYNC_SIG_YG, + SDO_SYNC_SIG_ALL +}; + +enum s5p_sdo_closed_caption_type { + SDO_NO_INS, + SDO_INS_1, + SDO_INS_2, + SDO_INS_OTHERS +}; + +enum s5p_sdo_525_copy_permit { + SDO_525_COPY_PERMIT, + SDO_525_ONECOPY_PERMIT, + SDO_525_NOCOPY_PERMIT +}; + +enum s5p_sdo_525_mv_psp { + SDO_525_MV_PSP_OFF, + SDO_525_MV_PSP_ON_2LINE_BURST, + SDO_525_MV_PSP_ON_BURST_OFF, + SDO_525_MV_PSP_ON_4LINE_BURST, +}; + +enum s5p_sdo_525_copy_info { + SDO_525_COPY_INFO, + SDO_525_DEFAULT, +}; + +enum s5p_sdo_525_aspect_ratio { + SDO_525_4_3_NORMAL, + SDO_525_16_9_ANAMORPIC, + SDO_525_4_3_LETTERBOX +}; + +enum s5p_sdo_625_subtitles { + SDO_625_NO_OPEN_SUBTITLES, + SDO_625_INACT_OPEN_SUBTITLES, + SDO_625_OUTACT_OPEN_SUBTITLES +}; + +enum s5p_sdo_625_camera_film { + SDO_625_CAMERA, + SDO_625_FILM +}; + +enum s5p_sdo_625_color_encoding { + SDO_625_NORMAL_PAL, + SDO_625_MOTION_ADAPTIVE_COLORPLUS +}; + +enum s5p_sdo_625_aspect_ratio { + SDO_625_4_3_FULL_576, + SDO_625_14_9_LETTERBOX_CENTER_504, + SDO_625_14_9_LETTERBOX_TOP_504, + SDO_625_16_9_LETTERBOX_CENTER_430, + SDO_625_16_9_LETTERBOX_TOP_430, + SDO_625_16_9_LETTERBOX_CENTER, + SDO_625_14_9_FULL_CENTER_576, + SDO_625_16_9_ANAMORPIC_576 +}; + +struct s5p_sdo_cvbs_compensation { + bool cvbs_color_compen; + u32 y_lower_mid; + u32 y_bottom; + u32 y_top; + u32 y_upper_mid; + u32 radius; +}; + +struct s5p_sdo_bright_hue_saturation { + bool bright_hue_sat_adj; + u32 gain_brightness; + u32 offset_brightness; + u32 gain0_cb_hue_sat; + u32 gain1_cb_hue_sat; + u32 gain0_cr_hue_sat; + u32 gain1_cr_hue_sat; + u32 offset_cb_hue_sat; + u32 offset_cr_hue_sat; +}; + +struct s5p_sdo_525_data { + bool analog_on; + enum s5p_sdo_525_copy_permit copy_permit; + enum s5p_sdo_525_mv_psp mv_psp; + enum s5p_sdo_525_copy_info copy_info; + enum s5p_sdo_525_aspect_ratio display_ratio; +}; + +struct s5p_sdo_625_data { + bool surround_sound; + bool copyright; + bool copy_protection; + bool text_subtitles; + enum s5p_sdo_625_subtitles open_subtitles; + enum s5p_sdo_625_camera_film camera_film; + enum s5p_sdo_625_color_encoding color_encoding; + bool helper_signal; + enum s5p_sdo_625_aspect_ratio display_ratio; +}; + +extern int s5p_sdo_set_video_scale_cfg(enum s5p_sdo_level composite_level, + enum s5p_sdo_vsync_ratio composite_ratio); +extern int s5p_sdo_set_vbi(bool wss_cvbs, + enum s5p_sdo_closed_caption_type caption_cvbs); +extern void s5p_sdo_set_offset_gain(u32 offset, u32 gain); +extern void s5p_sdo_set_delay(u32 delay_y, u32 offset_video_start, + u32 offset_video_end); +extern void s5p_sdo_set_schlock(bool color_sucarrier_pha_adj); +extern void s5p_sdo_set_brightness_hue_saturation(struct s5p_sdo_bright_hue_saturation bri_hue_sat); +extern void s5p_sdo_set_cvbs_color_compensation(struct s5p_sdo_cvbs_compensation cvbs_comp); +extern void s5p_sdo_set_component_porch(u32 back_525, u32 front_525, + u32 back_625, u32 front_625); +extern void s5p_sdo_set_ch_xtalk_cancel_coef(u32 coeff2, u32 coeff1); +extern void s5p_sdo_set_closed_caption(u32 display_cc, u32 non_display_cc); + +extern int s5p_sdo_set_wss525_data(struct s5p_sdo_525_data wss525); +extern int s5p_sdo_set_wss625_data(struct s5p_sdo_625_data wss625); +extern int s5p_sdo_set_cgmsa525_data(struct s5p_sdo_525_data cgmsa525); +extern int s5p_sdo_set_cgmsa625_data(struct s5p_sdo_625_data cgmsa625); +extern int s5p_sdo_set_display_mode(enum s5p_tvout_disp_mode disp_mode, + enum s5p_sdo_order order); +extern void s5p_sdo_clock_on(bool on); +extern void s5p_sdo_dac_on(bool on); +extern void s5p_sdo_sw_reset(bool active); +extern void s5p_sdo_set_interrupt_enable(bool vsync_intc_en); +extern void s5p_sdo_clear_interrupt_pending(void); +extern void s5p_sdo_init(void __iomem *addr); + +/* for VP */ + +enum s5p_vp_field { + VP_TOP_FIELD, + VP_BOTTOM_FIELD +}; + +enum s5p_vp_line_eq { + VP_LINE_EQ_0, + VP_LINE_EQ_1, + VP_LINE_EQ_2, + VP_LINE_EQ_3, + VP_LINE_EQ_4, + VP_LINE_EQ_5, + VP_LINE_EQ_6, + VP_LINE_EQ_7, + VP_LINE_EQ_DEFAULT +}; + +enum s5p_vp_mem_type { + VP_YUV420_NV12, + VP_YUV420_NV21 +}; + +enum s5p_vp_mem_mode { + VP_LINEAR_MODE, + VP_2D_TILE_MODE +}; + +enum s5p_vp_chroma_expansion { + VP_C_TOP, + VP_C_TOP_BOTTOM +}; + +enum s5p_vp_pxl_rate { + VP_PXL_PER_RATE_1_1, + VP_PXL_PER_RATE_1_2, + VP_PXL_PER_RATE_1_3, + VP_PXL_PER_RATE_1_4 +}; + +enum s5p_vp_sharpness_control { + VP_SHARPNESS_NO, + VP_SHARPNESS_MIN, + VP_SHARPNESS_MOD, + VP_SHARPNESS_MAX +}; + +enum s5p_vp_csc_type { + VP_CSC_SD_HD, + VP_CSC_HD_SD +}; + +enum s5p_vp_csc_coeff { + VP_CSC_Y2Y_COEF, + VP_CSC_CB2Y_COEF, + VP_CSC_CR2Y_COEF, + VP_CSC_Y2CB_COEF, + VP_CSC_CB2CB_COEF, + VP_CSC_CR2CB_COEF, + VP_CSC_Y2CR_COEF, + VP_CSC_CB2CR_COEF, + VP_CSC_CR2CR_COEF +}; + + +extern void s5p_vp_set_poly_filter_coef_default(u32 src_width, u32 src_height, + u32 dst_width, u32 dst_height, + bool ipc_2d); +extern void s5p_vp_set_field_id(enum s5p_vp_field mode); +extern int s5p_vp_set_top_field_address(u32 top_y_addr, u32 top_c_addr); +extern int s5p_vp_set_bottom_field_address(u32 bottom_y_addr, + u32 bottom_c_addr); +extern int s5p_vp_set_img_size(u32 img_width, u32 img_height); +extern void s5p_vp_set_src_position(u32 src_off_x, u32 src_x_fract_step, + u32 src_off_y); +extern void s5p_vp_set_dest_position(u32 dst_off_x, u32 dst_off_y); +extern void s5p_vp_set_src_dest_size(u32 src_width, u32 src_height, + u32 dst_width, u32 dst_height, + bool ipc_2d); +extern void s5p_vp_set_op_mode(bool line_skip, enum s5p_vp_mem_type mem_type, + enum s5p_vp_mem_mode mem_mode, + enum s5p_vp_chroma_expansion chroma_exp, + bool auto_toggling); +extern void s5p_vp_set_pixel_rate_control(enum s5p_vp_pxl_rate rate); +extern void s5p_vp_set_endian(enum s5p_tvout_endian endian); +extern void s5p_vp_set_bypass_post_process(bool bypass); +extern void s5p_vp_set_saturation(u32 sat); +extern void s5p_vp_set_sharpness(u32 th_h_noise, + enum s5p_vp_sharpness_control sharpness); +extern void s5p_vp_set_brightness_contrast(u16 b, u8 c); +extern void s5p_vp_set_brightness_offset(u32 offset); +extern int s5p_vp_set_brightness_contrast_control(enum s5p_vp_line_eq eq_num, + u32 intc, u32 slope); +extern void s5p_vp_set_csc_control(bool sub_y_offset_en, bool csc_en); +extern int s5p_vp_set_csc_coef(enum s5p_vp_csc_coeff csc_coeff, u32 coeff); +extern int s5p_vp_set_csc_coef_default(enum s5p_vp_csc_type csc_type); +extern int s5p_vp_update(void); +extern int s5p_vp_get_update_status(void); +extern void s5p_vp_sw_reset(void); +extern int s5p_vp_start(void); +extern int s5p_vp_stop(void); +extern void s5p_vp_init(void __iomem *addr); + +/* for CEC */ + +enum cec_state { + STATE_RX, + STATE_TX, + STATE_DONE, + STATE_ERROR +}; + +struct cec_rx_struct { + spinlock_t lock; + wait_queue_head_t waitq; + atomic_t state; + u8 *buffer; + unsigned int size; +}; + +struct cec_tx_struct { + wait_queue_head_t waitq; + atomic_t state; +}; + +extern struct cec_rx_struct cec_rx_struct; +extern struct cec_tx_struct cec_tx_struct; + +void s5p_cec_set_divider(void); +void s5p_cec_enable_rx(void); +void s5p_cec_mask_rx_interrupts(void); +void s5p_cec_unmask_rx_interrupts(void); +void s5p_cec_mask_tx_interrupts(void); +void s5p_cec_unmask_tx_interrupts(void); +void s5p_cec_reset(void); +void s5p_cec_tx_reset(void); +void s5p_cec_rx_reset(void); +void s5p_cec_threshold(void); +void s5p_cec_set_tx_state(enum cec_state state); +void s5p_cec_set_rx_state(enum cec_state state); +void s5p_cec_copy_packet(char *data, size_t count); +void s5p_cec_set_addr(u32 addr); +u32 s5p_cec_get_status(void); +void s5p_clr_pending_tx(void); +void s5p_clr_pending_rx(void); +void s5p_cec_get_rx_buf(u32 size, u8 *buffer); +void __init s5p_cec_mem_probe(struct platform_device *pdev); + +/* for HDCP */ + +extern int s5p_hdcp_encrypt_stop(bool on); +extern int __init s5p_hdcp_init(void); +extern int s5p_hdcp_start(void); +extern int s5p_hdcp_stop(void); + +#endif /* __S5P_TVOUT_HW_IF_H_ */ diff --git a/drivers/media/platform/s5p-tv/s5p-cec.c b/drivers/media/platform/s5p-tv/s5p-cec.c new file mode 100644 index 00000000000000..047f152a3188dc --- /dev/null +++ b/drivers/media/platform/s5p-tv/s5p-cec.c @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * CEC Support for Samsung S5P TVOUT + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include + +// Modified includes: +#include +#include + +#include "../../../arch/arm/plat-samsung/include/plat/tvout.h" + +#include "s5p_tvout_common_lib.h" +#include "hw_if/hw_if.h" + +#define CEC_IOC_MAGIC 'c' +#define CEC_IOC_SETLADDR _IOW(CEC_IOC_MAGIC, 0, unsigned int) + +/* /dev/cec (Major 10, Minor 242) */ +#define CEC_MINOR 242 + +#define CEC_STATUS_TX_DONE (1 << 2) +#define CEC_STATUS_TX_ERROR (1 << 3) +#define CEC_STATUS_RX_DONE (1 << 18) +#define CEC_STATUS_RX_ERROR (1 << 19) + +#define CEC_TX_BUFF_SIZE 16 + + +static atomic_t hdmi_on = ATOMIC_INIT(0); +static DEFINE_MUTEX(cec_lock); + +static int s5p_cec_open(struct inode *inode, struct file *file) +{ + int ret = 0; + + mutex_lock(&cec_lock); + + if (atomic_read(&hdmi_on)) { + tvout_dbg("do not allow multiple open for tvout cec\n"); + ret = -EBUSY; + goto err_multi_open; + } else + atomic_inc(&hdmi_on); + + s5p_cec_reset(); + + s5p_cec_set_divider(); + + s5p_cec_threshold(); + + s5p_cec_unmask_tx_interrupts(); + + s5p_cec_set_rx_state(STATE_RX); + s5p_cec_unmask_rx_interrupts(); + s5p_cec_enable_rx(); + +err_multi_open: + mutex_unlock(&cec_lock); + + return ret; +} + + +static int s5p_cec_release(struct inode *inode, struct file *file) +{ + atomic_dec(&hdmi_on); + + s5p_cec_mask_tx_interrupts(); + s5p_cec_mask_rx_interrupts(); + + return 0; +} + +static ssize_t s5p_cec_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) +{ + ssize_t retval; + + if (wait_event_interruptible(cec_rx_struct.waitq, atomic_read(&cec_rx_struct.state) == STATE_DONE)) + return -ERESTARTSYS; + + spin_lock_irq(&cec_rx_struct.lock); + + if (cec_rx_struct.size > count) { + spin_unlock_irq(&cec_rx_struct.lock); + + return -1; + } + + if (copy_to_user(buffer, cec_rx_struct.buffer, cec_rx_struct.size)) { + spin_unlock_irq(&cec_rx_struct.lock); + printk(KERN_ERR " copy_to_user() failed!\n"); + + return -EFAULT; + } + + retval = cec_rx_struct.size; + + s5p_cec_set_rx_state(STATE_RX); + spin_unlock_irq(&cec_rx_struct.lock); + + return retval; +} + + +static ssize_t s5p_cec_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ + char *data; + + /* check data size */ + + if (count > CEC_TX_BUFF_SIZE || count == 0) + return -1; + + data = kmalloc(count, GFP_KERNEL); + + if (!data) { + printk(KERN_ERR " kmalloc() failed!\n"); + + return -1; + } + + if (copy_from_user(data, buffer, count)) { + printk(KERN_ERR " copy_from_user() failed!\n"); + kfree(data); + + return -EFAULT; + } + + s5p_cec_copy_packet(data, count); + + kfree(data); + + /* wait for interrupt */ + if (wait_event_interruptible(cec_tx_struct.waitq, atomic_read(&cec_tx_struct.state) != STATE_TX)) + return -ERESTARTSYS; + + if (atomic_read(&cec_tx_struct.state) == STATE_ERROR) + return -1; + + return count; +} + +static long s5p_cec_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + u32 laddr; + + switch (cmd) { + case CEC_IOC_SETLADDR: + if (get_user(laddr, (u32 __user *) arg)) + return -EFAULT; + + tvout_dbg("logical address = 0x%02x\n", laddr); + + s5p_cec_set_addr(laddr); + break; + + default: + return -EINVAL; + } + + return 0; +} + +static u32 s5p_cec_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &cec_rx_struct.waitq, wait); + + if (atomic_read(&cec_rx_struct.state) == STATE_DONE) + return POLLIN | POLLRDNORM; + + return 0; +} + +static const struct file_operations cec_fops = { + .owner = THIS_MODULE, + .open = s5p_cec_open, + .release = s5p_cec_release, + .read = s5p_cec_read, + .write = s5p_cec_write, + .unlocked_ioctl = s5p_cec_ioctl, + .poll = s5p_cec_poll, +}; + +static struct miscdevice cec_misc_device = { + .minor = CEC_MINOR, + .name = "CEC", + .fops = &cec_fops, +}; + +static irqreturn_t s5p_cec_irq_handler(int irq, void *dev_id) +{ + u32 status = s5p_cec_get_status(); + + if (status & CEC_STATUS_TX_DONE) { + if (status & CEC_STATUS_TX_ERROR) { + tvout_dbg(" CEC_STATUS_TX_ERROR!\n"); + s5p_cec_set_tx_state(STATE_ERROR); + } else { + tvout_dbg(" CEC_STATUS_TX_DONE!\n"); + s5p_cec_set_tx_state(STATE_DONE); + } + + s5p_clr_pending_tx(); + + wake_up_interruptible(&cec_tx_struct.waitq); + } + + if (status & CEC_STATUS_RX_DONE) { + if (status & CEC_STATUS_RX_ERROR) { + tvout_dbg(" CEC_STATUS_RX_ERROR!\n"); + s5p_cec_rx_reset(); + + } else { + u32 size; + + tvout_dbg(" CEC_STATUS_RX_DONE!\n"); + + /* copy data from internal buffer */ + size = status >> 24; + + spin_lock(&cec_rx_struct.lock); + + s5p_cec_get_rx_buf(size, cec_rx_struct.buffer); + + cec_rx_struct.size = size; + + s5p_cec_set_rx_state(STATE_DONE); + + spin_unlock(&cec_rx_struct.lock); + + s5p_cec_enable_rx(); + } + + /* clear interrupt pending bit */ + s5p_clr_pending_rx(); + + wake_up_interruptible(&cec_rx_struct.waitq); + } + return IRQ_HANDLED; +} + +static int __init s5p_cec_probe(struct platform_device *pdev) +{ + struct s5p_platform_cec *pdata; + u8 *buffer = NULL; + int irq_num; + int ret = 0; + + pdata = to_tvout_plat(&pdev->dev); + + if (pdata->cfg_gpio) + pdata->cfg_gpio(pdev); + + /* get ioremap addr */ + s5p_cec_mem_probe(pdev); + + if (misc_register(&cec_misc_device)) { + printk(KERN_WARNING " Couldn't register device 10, %d.\n", CEC_MINOR); + ret = -EBUSY; + goto out; + } + + irq_num = platform_get_irq(pdev, 0); + if (irq_num < 0) { + printk(KERN_ERR "failed to get %s irq resource\n", "cec"); + ret = -EBUSY; + goto irq_err; + } + + if (request_irq(irq_num, s5p_cec_irq_handler, IRQF_DISABLED, pdev->name, &pdev->id)) { + printk(KERN_ERR "failed to install %s irq (%d)\n", "cec", ret); + ret = -EBUSY; + goto irq_err; + } + + init_waitqueue_head(&cec_rx_struct.waitq); + spin_lock_init(&cec_rx_struct.lock); + init_waitqueue_head(&cec_tx_struct.waitq); + + if (kmalloc(CEC_TX_BUFF_SIZE, GFP_KERNEL)) { + printk(KERN_ERR " kmalloc() failed!\n"); + ret = -EIO; + goto kmalloc_err; + } + + cec_rx_struct.buffer = buffer; + cec_rx_struct.size = 0; + + return 0; + +kmalloc_err: + free_irq(irq_num, NULL); +irq_err: + misc_deregister(&cec_misc_device); +out: + return ret; + +} + +static int s5p_cec_remove(struct platform_device *pdev) +{ + int irq_num = platform_get_irq(pdev, 0); + + free_irq(irq_num, NULL); + misc_deregister(&cec_misc_device); + + return 0; +} + +#ifdef CONFIG_PM +static int s5p_cec_suspend(struct platform_device *dev, pm_message_t state) +{ + return 0; +} + +static int s5p_cec_resume(struct platform_device *dev) +{ + return 0; +} + +#else +#define s5p_cec_suspend NULL +#define s5p_cec_resume NULL +#endif + +static struct platform_driver s5p_cec_driver = { + .probe = s5p_cec_probe, + .remove = s5p_cec_remove, + .suspend = s5p_cec_suspend, + .resume = s5p_cec_resume, + .driver = { + .name = "s5p-tvout-cec", + .owner = THIS_MODULE, + }, +}; + +static int __init s5p_cec_init(void) +{ + printk(KERN_INFO "S5P CEC for TVOUT Driver, Copyright (c) 2011 Samsung Electronics Co., LTD.\n"); + + return platform_driver_register(&s5p_cec_driver); +} + +static void __exit s5p_cec_exit(void) +{ + kfree(cec_rx_struct.buffer); + + platform_driver_unregister(&s5p_cec_driver); +} +module_init(s5p_cec_init); +module_exit(s5p_cec_exit); + +MODULE_AUTHOR("KyungHwan Kim "); +MODULE_DESCRIPTION("Samsung S5P CEC driver"); +MODULE_LICENSE("GPL"); + + From 28ade54c99b92165e4366c53b13288640e5b81ae Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sat, 29 Jun 2013 14:56:40 +0200 Subject: [PATCH 02/30] ahh!, it compiles. not tested yet. --- arch/arm/plat-samsung/include/plat/devs.h | 1 + drivers/media/platform/s5p-tv/Makefile | 8 +- .../platform/s5p-tv/{s5p-cec.c => cec_drv.c} | 26 ++- .../platform/s5p-tv/s5p_tvout_common_lib.c | 99 ++++++++++ .../platform/s5p-tv/s5p_tvout_common_lib.h | 187 ++++++++++++++++++ 5 files changed, 313 insertions(+), 8 deletions(-) rename drivers/media/platform/s5p-tv/{s5p-cec.c => cec_drv.c} (91%) create mode 100644 drivers/media/platform/s5p-tv/s5p_tvout_common_lib.c create mode 100644 drivers/media/platform/s5p-tv/s5p_tvout_common_lib.h diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 92641bb13ef8d1..310e629afa7f8e 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -87,6 +87,7 @@ extern struct platform_device mali_gpu_device; extern struct platform_device s5p_device_fimd0; extern struct platform_device s5p_device_hdmi; +extern struct platform_device s5p_device_hdmi_cec; extern struct platform_device s5p_device_i2c_hdmiphy; extern struct platform_device s5p_device_mfc; extern struct platform_device s5p_device_mfc_l; diff --git a/drivers/media/platform/s5p-tv/Makefile b/drivers/media/platform/s5p-tv/Makefile index 08137955d63657..1faf3b90b9de53 100644 --- a/drivers/media/platform/s5p-tv/Makefile +++ b/drivers/media/platform/s5p-tv/Makefile @@ -8,15 +8,19 @@ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMIPHY) += s5p-hdmiphy.o s5p-hdmiphy-y += hdmiphy_drv.o + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SII9234) += s5p-sii9234.o s5p-sii9234-y += sii9234_drv.o + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMI) += s5p-hdmi.o s5p-hdmi-$(CONFIG_CPU_EXYNOS4210) += hdmi_drv.o s5p-hdmi-$(CONFIG_SOC_EXYNOS4412) += hdmi_v14_drv.o -# obj-$(VIDEO_SAMSUNG_S5P_HDMI_CEC) += s5p-cec.o -s5p-cec-$(VIDEO_SAMSUNG_S5P_HDMI_CEC) += s5p-cec.o + +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMI_CEC) += s5p-cec.o +s5p-cec-y += cec_drv.o obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SDO) += s5p-sdo.o s5p-sdo-y += sdo_drv.o + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MIXER) += s5p-mixer.o s5p-mixer-y += mixer_drv.o mixer_video.o mixer_reg.o mixer_grp_layer.o mixer_vp_layer.o diff --git a/drivers/media/platform/s5p-tv/s5p-cec.c b/drivers/media/platform/s5p-tv/cec_drv.c similarity index 91% rename from drivers/media/platform/s5p-tv/s5p-cec.c rename to drivers/media/platform/s5p-tv/cec_drv.c index 047f152a3188dc..40b864680ec057 100644 --- a/drivers/media/platform/s5p-tv/s5p-cec.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -17,8 +17,13 @@ // Modified includes: #include #include +#include + +//#include "../../../arch/arm/plat-samsung/include/plat/tvout.h" +struct s5p_platform_cec { + void (*cfg_gpio)(struct platform_device *pdev); +}; -#include "../../../arch/arm/plat-samsung/include/plat/tvout.h" #include "s5p_tvout_common_lib.h" #include "hw_if/hw_if.h" @@ -87,6 +92,8 @@ static ssize_t s5p_cec_read(struct file *file, char __user *buffer, { ssize_t retval; + printk("s5p_cec_read, count = %lu", (unsigned long)count); + if (wait_event_interruptible(cec_rx_struct.waitq, atomic_read(&cec_rx_struct.state) == STATE_DONE)) return -ERESTARTSYS; @@ -157,6 +164,8 @@ static long s5p_cec_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { u32 laddr; + + printk("s5p_cec_read, cmd = %u, arg = %lu", cmd, arg); switch (cmd) { case CEC_IOC_SETLADDR: @@ -253,7 +262,7 @@ static irqreturn_t s5p_cec_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static int __init s5p_cec_probe(struct platform_device *pdev) +static int s5p_cec_probe(struct platform_device *pdev) { struct s5p_platform_cec *pdata; u8 *buffer = NULL; @@ -261,7 +270,8 @@ static int __init s5p_cec_probe(struct platform_device *pdev) int ret = 0; pdata = to_tvout_plat(&pdev->dev); - + printk("s5p_cec_probe: pdata=0x%08x\n", pdata); + if (pdata->cfg_gpio) pdata->cfg_gpio(pdev); @@ -357,6 +367,8 @@ static int __init s5p_cec_init(void) static void __exit s5p_cec_exit(void) { + printk(KERN_INFO "S5P CEC for TVOUT Driver, exiting\n"); + kfree(cec_rx_struct.buffer); platform_driver_unregister(&s5p_cec_driver); @@ -364,8 +376,10 @@ static void __exit s5p_cec_exit(void) module_init(s5p_cec_init); module_exit(s5p_cec_exit); -MODULE_AUTHOR("KyungHwan Kim "); -MODULE_DESCRIPTION("Samsung S5P CEC driver"); -MODULE_LICENSE("GPL"); +//module_platform_driver(s5p_cec_driver); + +//MODULE_AUTHOR("KyungHwan Kim "); +//MODULE_DESCRIPTION("Samsung S5P CEC driver"); +//MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/s5p-tv/s5p_tvout_common_lib.c b/drivers/media/platform/s5p-tv/s5p_tvout_common_lib.c new file mode 100644 index 00000000000000..550efe041f47cc --- /dev/null +++ b/drivers/media/platform/s5p-tv/s5p_tvout_common_lib.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Common library for SAMSUNG S5P TVOUT driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include + +#include + +#include "s5p_tvout_common_lib.h" + +int s5p_tvout_map_resource_mem(struct platform_device *pdev, char *name, + void __iomem **base, struct resource **res) +{ + size_t size; + void __iomem *tmp_base; + struct resource *tmp_res; + + tmp_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); + + if (!tmp_res) + goto not_found; + + size = resource_size(tmp_res); + + tmp_res = request_mem_region(tmp_res->start, size, tmp_res->name); + + if (!tmp_res) { + tvout_err("%s: fail to get memory region\n", __func__); + goto err_on_request_mem_region; + } + + tmp_base = ioremap(tmp_res->start, size); + + if (!tmp_base) { + tvout_err("%s: fail to ioremap address region\n", __func__); + goto err_on_ioremap; + } + + *res = tmp_res; + *base = tmp_base; + return 0; + +err_on_ioremap: + release_resource(tmp_res); + kfree(tmp_res); + +err_on_request_mem_region: + return -ENXIO; + +not_found: + tvout_err("%s: fail to get IORESOURCE_MEM for %s\n", __func__, name); + return -ENODEV; +} + +void s5p_tvout_unmap_resource_mem(void __iomem *base, struct resource *res) +{ + if (!base) + iounmap(base); + + if (res != NULL) { + release_resource(res); + kfree(res); + } +} + +/* Libraries for runtime PM */ + +static struct device *s5p_tvout_dev; + +void s5p_tvout_pm_runtime_enable(struct device *dev) +{ + pm_runtime_enable(dev); + + s5p_tvout_dev = dev; +} + +void s5p_tvout_pm_runtime_disable(struct device *dev) +{ + pm_runtime_disable(dev); +} + +void s5p_tvout_pm_runtime_get(void) +{ + pm_runtime_get_sync(s5p_tvout_dev); +} + +void s5p_tvout_pm_runtime_put(void) +{ + pm_runtime_put_sync(s5p_tvout_dev); +} diff --git a/drivers/media/platform/s5p-tv/s5p_tvout_common_lib.h b/drivers/media/platform/s5p-tv/s5p_tvout_common_lib.h new file mode 100644 index 00000000000000..7e87a03d142d77 --- /dev/null +++ b/drivers/media/platform/s5p-tv/s5p_tvout_common_lib.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Header file of common library for SAMSUNG S5P TVOUT driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __S5P_TVOUT_COMMON_LIB_H_ +#define __S5P_TVOUT_COMMON_LIB_H_ __FILE__ + +#include +#include +#include +#include + +/* + * This file includes declarations for TVOUT driver's common library. + * All files in TVOUT driver can access function or definition in this file. + */ + +#define DRV_NAME "S5P-TVOUT" + +#define tvout_err(fmt, ...) \ + printk(KERN_ERR "[%s] %s(): " fmt, \ + DRV_NAME, __func__, ##__VA_ARGS__) + +#ifndef tvout_dbg +#ifdef CONFIG_S5P_TVOUT_DEBUG +#define tvout_dbg(fmt, ...) \ + printk(KERN_INFO "[%s] %s(): " fmt, \ + DRV_NAME, __func__, ##__VA_ARGS__) +#else +#define tvout_dbg(fmt, ...) +#endif +#endif + +#define S5PTV_FB_CNT 2 +#define HDMI_START_NUM 0x1000 + +#define to_tvout_plat(d) (to_platform_device(d)->dev.platform_data) + +enum s5p_tvout_disp_mode { + TVOUT_NTSC_M, + TVOUT_PAL_BDGHI, + TVOUT_PAL_M, + TVOUT_PAL_N, + TVOUT_PAL_NC, + TVOUT_PAL_60, + TVOUT_NTSC_443, + + TVOUT_480P_60_16_9 = HDMI_START_NUM, + TVOUT_480P_60_4_3, + TVOUT_480P_59, + + TVOUT_576P_50_16_9, + TVOUT_576P_50_4_3, + + TVOUT_720P_60, + TVOUT_720P_50, + TVOUT_720P_59, + + TVOUT_1080P_60, + TVOUT_1080P_50, + TVOUT_1080P_59, + TVOUT_1080P_30, + + TVOUT_1080I_60, + TVOUT_1080I_50, + TVOUT_1080I_59, + TVOUT_INIT_DISP_VALUE +}; + +enum s5p_tvout_o_mode { + TVOUT_COMPOSITE, + TVOUT_HDMI, + TVOUT_HDMI_RGB, + TVOUT_DVI, + TVOUT_INIT_O_VALUE +}; + +enum s5p_mixer_burst_mode { + MIXER_BURST_8, + MIXER_BURST_16, +}; + +enum s5ptvfb_data_path_t { + DATA_PATH_FIFO, + DATA_PATH_DMA, +}; + +enum s5ptvfb_alpha_t { + LAYER_BLENDING, + PIXEL_BLENDING, + NONE_BLENDING, +}; + +enum s5ptvfb_ver_scaling_t { + VERTICAL_X1, + VERTICAL_X2, +}; + +enum s5ptvfb_hor_scaling_t { + HORIZONTAL_X1, + HORIZONTAL_X2, +}; + +struct s5ptvfb_alpha { + enum s5ptvfb_alpha_t mode; + int channel; + unsigned int value; +}; + +struct s5ptvfb_chroma { + int enabled; + unsigned int key; +}; + +struct s5ptvfb_user_window { + int x; + int y; +}; + +struct s5ptvfb_user_plane_alpha { + int channel; + unsigned char alpha; +}; + +struct s5ptvfb_user_chroma { + int enabled; + unsigned char red; + unsigned char green; + unsigned char blue; +}; + +struct s5ptvfb_user_scaling { + enum s5ptvfb_ver_scaling_t ver; + enum s5ptvfb_hor_scaling_t hor; +}; + +struct s5p_tvout_status { + struct clk *i2c_phy_clk; + struct clk *sclk_hdmiphy; + struct clk *sclk_pixel; + struct clk *sclk_dac; + struct clk *sclk_hdmi; +}; + +struct reg_mem_info { + char *name; + struct resource *res; + void __iomem *base; +}; + +struct irq_info { + char *name; + irq_handler_t handler; + int no; +}; + +struct s5p_tvout_clk_info { + char *name; + struct clk *ptr; +}; + +extern struct s5p_tvout_status s5ptv_status; + +extern int s5p_tvout_vcm_create_unified(void); +extern int s5p_tvout_vcm_init(void); +extern void s5p_tvout_vcm_activate(void); +extern void s5p_tvout_vcm_deactivate(void); + +extern int s5p_tvout_map_resource_mem(struct platform_device *pdev, + char *name, void __iomem **base, + struct resource **res); +extern void s5p_tvout_unmap_resource_mem(void __iomem *base, + struct resource *res); + +extern void s5p_tvout_pm_runtime_enable(struct device *dev); +extern void s5p_tvout_pm_runtime_disable(struct device *dev); +extern void s5p_tvout_pm_runtime_get(void); +extern void s5p_tvout_pm_runtime_put(void); + +#endif /* __S5P_TVOUT_COMMON_LIB_H_ */ From 884d231b1fd8321efa96af1330f8cc0f9a563f19 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sat, 29 Jun 2013 15:52:35 +0200 Subject: [PATCH 03/30] low-level initialization functions still not tested --- arch/arm/plat-samsung/devs.c | 2 +- drivers/media/platform/s5p-tv/Makefile | 2 +- drivers/media/platform/s5p-tv/cec_drv.c | 16 +--- drivers/media/platform/s5p-tv/hw_if/cec.c | 1 + .../media/platform/s5p-tv/hw_if/regs-cec.h | 95 +++++++++++++++++++ 5 files changed, 103 insertions(+), 13 deletions(-) create mode 100644 drivers/media/platform/s5p-tv/hw_if/regs-cec.h diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index 099173ed43f79d..4614ad9a530090 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c @@ -1360,7 +1360,7 @@ struct platform_device s5p_device_hdmi = { struct platform_device s5p_device_hdmi_cec = { .name = "s5p-cec", .id = -1, - .num_resources = 0; //ARRAY_SIZE(s5p_hdmi_resources), + .num_resources = 0, //ARRAY_SIZE(s5p_hdmi_resources), .resource = s5p_hdmi_resources, }; diff --git a/drivers/media/platform/s5p-tv/Makefile b/drivers/media/platform/s5p-tv/Makefile index 1faf3b90b9de53..893dbca1b54d77 100644 --- a/drivers/media/platform/s5p-tv/Makefile +++ b/drivers/media/platform/s5p-tv/Makefile @@ -20,7 +20,7 @@ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMI_CEC) += s5p-cec.o s5p-cec-y += cec_drv.o obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SDO) += s5p-sdo.o -s5p-sdo-y += sdo_drv.o +s5p-sdo-y += sdo_drv.o hw_if/cec.o obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MIXER) += s5p-mixer.o s5p-mixer-y += mixer_drv.o mixer_video.o mixer_reg.o mixer_grp_layer.o mixer_vp_layer.o diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index 40b864680ec057..6312492f3b49bf 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -270,7 +270,7 @@ static int s5p_cec_probe(struct platform_device *pdev) int ret = 0; pdata = to_tvout_plat(&pdev->dev); - printk("s5p_cec_probe: pdata=0x%08x\n", pdata); + printk(KERN_INFO "s5p_cec_probe: pdata=%p\n", pdata); if (pdata->cfg_gpio) pdata->cfg_gpio(pdev); @@ -361,25 +361,19 @@ static struct platform_driver s5p_cec_driver = { static int __init s5p_cec_init(void) { printk(KERN_INFO "S5P CEC for TVOUT Driver, Copyright (c) 2011 Samsung Electronics Co., LTD.\n"); - return platform_driver_register(&s5p_cec_driver); } static void __exit s5p_cec_exit(void) { printk(KERN_INFO "S5P CEC for TVOUT Driver, exiting\n"); - kfree(cec_rx_struct.buffer); - platform_driver_unregister(&s5p_cec_driver); } + module_init(s5p_cec_init); module_exit(s5p_cec_exit); -//module_platform_driver(s5p_cec_driver); - -//MODULE_AUTHOR("KyungHwan Kim "); -//MODULE_DESCRIPTION("Samsung S5P CEC driver"); -//MODULE_LICENSE("GPL"); - - +MODULE_AUTHOR("KyungHwan Kim "); +MODULE_DESCRIPTION("Samsung S5P CEC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/s5p-tv/hw_if/cec.c b/drivers/media/platform/s5p-tv/hw_if/cec.c index dbff584203e8a2..24f28cb26a684b 100644 --- a/drivers/media/platform/s5p-tv/hw_if/cec.c +++ b/drivers/media/platform/s5p-tv/hw_if/cec.c @@ -18,6 +18,7 @@ #include "../s5p_tvout_common_lib.h" #include "hw_if.h" +#include "regs-cec.h" // TODO: move to /arch/arm/plat* #define S5P_HDMI_FIN 24000000 #define CEC_DIV_RATIO 320000 diff --git a/drivers/media/platform/s5p-tv/hw_if/regs-cec.h b/drivers/media/platform/s5p-tv/hw_if/regs-cec.h new file mode 100644 index 00000000000000..6a86d6e153a263 --- /dev/null +++ b/drivers/media/platform/s5p-tv/hw_if/regs-cec.h @@ -0,0 +1,95 @@ +/* linux/drivers/media/video/samsung/tv20/s5pc100/regs/regs-cec.h + * + * Copyright (c) 2009 Samsung Electronics + * http://www.samsungsemi.com/ + * + * CEC register header file for Samsung TVOut driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* + * Source: + * http://code.google.com/p/openwrt-for-embedded/source/browse/trunk/target/linux/s5pv210/files-2.6.35/arch/arm/plat-s5p/include/plat/regs-cec.h?r=56 + */ + +#ifndef __REGS_CEC_H +#define __REGS_CEC_H + +#define HDMIDP_CECREG(x) (x) + +#define S5P_CEC_STATUS_0 HDMIDP_CECREG(0x0000) +#define S5P_CEC_STATUS_1 HDMIDP_CECREG(0x0004) +#define S5P_CEC_STATUS_2 HDMIDP_CECREG(0x0008) +#define S5P_CEC_STATUS_3 HDMIDP_CECREG(0x000C) +#define S5P_CEC_IRQ_MASK HDMIDP_CECREG(0x0010) +#define S5P_CEC_IRQ_CLEAR HDMIDP_CECREG(0x0014) +#define S5P_CEC_LOGIC_ADDR HDMIDP_CECREG(0x0020) +#define S5P_CEC_DIVISOR_0 HDMIDP_CECREG(0x0030) +#define S5P_CEC_DIVISOR_1 HDMIDP_CECREG(0x0034) +#define S5P_CEC_DIVISOR_2 HDMIDP_CECREG(0x0038) +#define S5P_CEC_DIVISOR_3 HDMIDP_CECREG(0x003C) + +#define S5P_CEC_TX_CTRL HDMIDP_CECREG(0x0040) +#define S5P_CEC_TX_BYTES HDMIDP_CECREG(0x0044) +#define S5P_CEC_TX_STAT0 HDMIDP_CECREG(0x0060) +#define S5P_CEC_TX_STAT1 HDMIDP_CECREG(0x0064) +#define S5P_CEC_TX_BUFF0 HDMIDP_CECREG(0x0080) +#define S5P_CEC_TX_BUFF1 HDMIDP_CECREG(0x0084) +#define S5P_CEC_TX_BUFF2 HDMIDP_CECREG(0x0088) +#define S5P_CEC_TX_BUFF3 HDMIDP_CECREG(0x008C) +#define S5P_CEC_TX_BUFF4 HDMIDP_CECREG(0x0090) +#define S5P_CEC_TX_BUFF5 HDMIDP_CECREG(0x0094) +#define S5P_CEC_TX_BUFF6 HDMIDP_CECREG(0x0098) +#define S5P_CEC_TX_BUFF7 HDMIDP_CECREG(0x009C) +#define S5P_CEC_TX_BUFF8 HDMIDP_CECREG(0x00A0) +#define S5P_CEC_TX_BUFF9 HDMIDP_CECREG(0x00A4) +#define S5P_CEC_TX_BUFF10 HDMIDP_CECREG(0x00A8) +#define S5P_CEC_TX_BUFF11 HDMIDP_CECREG(0x00AC) +#define S5P_CEC_TX_BUFF12 HDMIDP_CECREG(0x00B0) +#define S5P_CEC_TX_BUFF13 HDMIDP_CECREG(0x00B4) +#define S5P_CEC_TX_BUFF14 HDMIDP_CECREG(0x00B8) +#define S5P_CEC_TX_BUFF15 HDMIDP_CECREG(0x00BC) + +#define S5P_CEC_RX_CTRL HDMIDP_CECREG(0x00C0) +#define S5P_CEC_RX_STAT0 HDMIDP_CECREG(0x00E0) +#define S5P_CEC_RX_STAT1 HDMIDP_CECREG(0x00E4) +#define S5P_CEC_RX_BUFF0 HDMIDP_CECREG(0x0100) +#define S5P_CEC_RX_BUFF1 HDMIDP_CECREG(0x0104) +#define S5P_CEC_RX_BUFF2 HDMIDP_CECREG(0x0108) +#define S5P_CEC_RX_BUFF3 HDMIDP_CECREG(0x010C) +#define S5P_CEC_RX_BUFF4 HDMIDP_CECREG(0x0110) +#define S5P_CEC_RX_BUFF5 HDMIDP_CECREG(0x0114) +#define S5P_CEC_RX_BUFF6 HDMIDP_CECREG(0x0118) +#define S5P_CEC_RX_BUFF7 HDMIDP_CECREG(0x011C) +#define S5P_CEC_RX_BUFF8 HDMIDP_CECREG(0x0120) +#define S5P_CEC_RX_BUFF9 HDMIDP_CECREG(0x0124) +#define S5P_CEC_RX_BUFF10 HDMIDP_CECREG(0x0128) +#define S5P_CEC_RX_BUFF11 HDMIDP_CECREG(0x012C) +#define S5P_CEC_RX_BUFF12 HDMIDP_CECREG(0x0130) +#define S5P_CEC_RX_BUFF13 HDMIDP_CECREG(0x0134) +#define S5P_CEC_RX_BUFF14 HDMIDP_CECREG(0x0138) +#define S5P_CEC_RX_BUFF15 HDMIDP_CECREG(0x013C) + +#define S5P_CEC_RX_FILTER_CTRL HDMIDP_CECREG(0x0180) +#define S5P_CEC_RX_FILTER_TH HDMIDP_CECREG(0x0184) + +#define S5P_CEC_IRQ_TX_DONE (1<<0) +#define S5P_CEC_IRQ_TX_ERROR (1<<1) +#define S5P_CEC_IRQ_RX_DONE (1<<4) +#define S5P_CEC_IRQ_RX_ERROR (1<<5) + +#define S5P_CEC_TX_CTRL_START (1<<0) +#define S5P_CEC_TX_CTRL_BCAST (1<<1) +#define S5P_CEC_TX_CTRL_RETRY (0x04<<4) +#define S5P_CEC_TX_CTRL_RESET (1<<7) + +#define S5P_CEC_RX_CTRL_ENABLE (1<<0) +#define S5P_CEC_RX_CTRL_RESET (1<<7) + +#define S5P_CEC_LOGIC_ADDR_MASK 0x0F + +#endif /* __REGS_CEC_H */ + From 37fc68ac3a5bdcc626cbeaa34b8625d724f9542d Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 10:26:27 +0200 Subject: [PATCH 04/30] add intro to README --- README | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README b/README index a24ec89ba4420a..8d5cb363bd413a 100644 --- a/README +++ b/README @@ -1,3 +1,20 @@ +Summary: + Trying to get CEC (tv-remote control over HDMI) working on linux. + +Status: + Copied s5p-cec code from all over the internet + Made it compile as module (s5p-cec.ko) + Not tested in any way + +TODO: + Try to load the module, and observe how it crashes + Fix the crash + Look at the latest android kernel sources http://dn.odroid.com/Android_Alpha_4.0.3/BSP/ + Cleanup this tree, so it becomes a minimal diff upon hardkernel's 3.8 tree + + +================================================================================================= + Linux kernel release 3.x These are the release notes for Linux version 3. Read them carefully, From 71c93c3888854db76892c529ecc5d18628f3ffbc Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 10:54:14 +0200 Subject: [PATCH 05/30] make it 'insmod' succesfully --- README | 7 ++++--- build.sh | 7 +++++++ drivers/media/platform/s5p-tv/Makefile | 4 ++-- drivers/media/platform/s5p-tv/hw_if/cec.c | 2 +- drivers/media/platform/s5p-tv/hw_if/hw_if.h | 2 +- 5 files changed, 15 insertions(+), 7 deletions(-) create mode 100755 build.sh diff --git a/README b/README index 8d5cb363bd413a..ec7b0ee04e2e9b 100644 --- a/README +++ b/README @@ -1,14 +1,15 @@ Summary: Trying to get CEC (tv-remote control over HDMI) working on linux. + There appear to be android-kernel sources. + The hardkernel linux doesn't have them Status: Copied s5p-cec code from all over the internet Made it compile as module (s5p-cec.ko) - Not tested in any way + It can be insmod-ed succesfully, that's all TODO: - Try to load the module, and observe how it crashes - Fix the crash + Make it do something Look at the latest android kernel sources http://dn.odroid.com/Android_Alpha_4.0.3/BSP/ Cleanup this tree, so it becomes a minimal diff upon hardkernel's 3.8 tree diff --git a/build.sh b/build.sh new file mode 100755 index 00000000000000..f7cb298d1c65f1 --- /dev/null +++ b/build.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +export CROSS_COMPILE=arm-linux-gnueabihf- +export ARCH=arm + +make M=drivers/media/platform/s5p-tv modules +scp drivers/media/platform/s5p-tv/s5p-cec.ko root@x2_wifi:/root diff --git a/drivers/media/platform/s5p-tv/Makefile b/drivers/media/platform/s5p-tv/Makefile index 893dbca1b54d77..10231b74abb43b 100644 --- a/drivers/media/platform/s5p-tv/Makefile +++ b/drivers/media/platform/s5p-tv/Makefile @@ -17,10 +17,10 @@ s5p-hdmi-$(CONFIG_CPU_EXYNOS4210) += hdmi_drv.o s5p-hdmi-$(CONFIG_SOC_EXYNOS4412) += hdmi_v14_drv.o obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMI_CEC) += s5p-cec.o -s5p-cec-y += cec_drv.o +s5p-cec-y += cec_drv.o hw_if/cec.o obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SDO) += s5p-sdo.o -s5p-sdo-y += sdo_drv.o hw_if/cec.o +s5p-sdo-y += sdo_drv.o obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MIXER) += s5p-mixer.o s5p-mixer-y += mixer_drv.o mixer_video.o mixer_reg.o mixer_grp_layer.o mixer_vp_layer.o diff --git a/drivers/media/platform/s5p-tv/hw_if/cec.c b/drivers/media/platform/s5p-tv/hw_if/cec.c index 24f28cb26a684b..9e5677699d141f 100644 --- a/drivers/media/platform/s5p-tv/hw_if/cec.c +++ b/drivers/media/platform/s5p-tv/hw_if/cec.c @@ -196,7 +196,7 @@ void s5p_cec_get_rx_buf(u32 size, u8 *buffer) } } -void __init s5p_cec_mem_probe(struct platform_device *pdev) +void s5p_cec_mem_probe(struct platform_device *pdev) { struct resource *res; size_t size = 0; diff --git a/drivers/media/platform/s5p-tv/hw_if/hw_if.h b/drivers/media/platform/s5p-tv/hw_if/hw_if.h index ac461666106e1b..b13fa54547871d 100644 --- a/drivers/media/platform/s5p-tv/hw_if/hw_if.h +++ b/drivers/media/platform/s5p-tv/hw_if/hw_if.h @@ -639,7 +639,7 @@ u32 s5p_cec_get_status(void); void s5p_clr_pending_tx(void); void s5p_clr_pending_rx(void); void s5p_cec_get_rx_buf(u32 size, u8 *buffer); -void __init s5p_cec_mem_probe(struct platform_device *pdev); +void s5p_cec_mem_probe(struct platform_device *pdev); /* for HDCP */ From 2aabc8985b3209167d4c814ef36608768fd74ecf Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 12:13:17 +0200 Subject: [PATCH 06/30] define resources, maybe now it probes() ? --- arch/arm/mach-s5pv210/include/mach/map.h | 4 ++++ arch/arm/plat-samsung/devs.c | 13 +++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h index b7c8a1917ffce5..660809b6a883f6 100644 --- a/arch/arm/mach-s5pv210/include/mach/map.h +++ b/arch/arm/mach-s5pv210/include/mach/map.h @@ -48,6 +48,10 @@ #define S5PV210_PA_PCM1 0xE1200000 #define S5PV210_PA_PCM2 0xE2B00000 +#define S5PV210_PA_CEC (0xE1B00000) +#define S5P_PA_CEC S5PV210_PA_CEC +#define S5P_SZ_CEC SZ_4K + #define S5PV210_PA_TIMER 0xE2500000 #define S5PV210_PA_SYSTIMER 0xE2600000 #define S5PV210_PA_WATCHDOG 0xE2700000 diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index 4614ad9a530090..cc09ca1429b60a 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c @@ -1357,11 +1357,16 @@ struct platform_device s5p_device_hdmi = { .resource = s5p_hdmi_resources, }; +static struct resource s5p_cec_resources[] = { + [0] = DEFINE_RES_MEM(S5P_PA_CEC, S5P_SZ_CEC), + [1] = DEFINE_RES_IRQ(IRQ_CEC), +}; + struct platform_device s5p_device_hdmi_cec = { - .name = "s5p-cec", - .id = -1, - .num_resources = 0, //ARRAY_SIZE(s5p_hdmi_resources), - .resource = s5p_hdmi_resources, + .name = "s5p-cec", + .id = -1, + .num_resources = ARRAY_SIZE(s5p_cec_resources), + .resource = s5p_cec_resources, }; static struct resource s5p_sdo_resources[] = { From ddab47c8bf788bf904e5f102bd4c4952a1a4e915 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 13:11:02 +0200 Subject: [PATCH 07/30] resources for exynos4 --- arch/arm/mach-exynos/include/mach/irqs.h | 3 +++ arch/arm/mach-exynos/include/mach/map.h | 5 ++++ arch/arm/mach-s5pv210/include/mach/map.h | 2 +- arch/arm/plat-samsung/devs.c | 2 +- drivers/media/platform/s5p-tv/cec_drv.c | 30 ++++++++++++++++++++---- 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h index 1f4dc35cd4b9b8..f5b0f19ae43ccf 100644 --- a/arch/arm/mach-exynos/include/mach/irqs.h +++ b/arch/arm/mach-exynos/include/mach/irqs.h @@ -132,6 +132,7 @@ #define EXYNOS4_IRQ_GPS IRQ_SPI(111) #define EXYNOS4_IRQ_INTFEEDCTRL_SSS IRQ_SPI(112) #define EXYNOS4_IRQ_SLIMBUS IRQ_SPI(113) +#define EXYNOS4_IRQ_CEC IRQ_SPI(114) #define EXYNOS4_IRQ_TSI IRQ_SPI(115) #define EXYNOS4_IRQ_SATA IRQ_SPI(116) @@ -235,6 +236,8 @@ #define IRQ_KEYPAD EXYNOS4_IRQ_KEYPAD #define IRQ_PMU EXYNOS4_IRQ_PMU +#define IRQ_CEC EXYNOS4_IRQ_CEC + #define IRQ_FIMD0_FIFO EXYNOS4_IRQ_FIMD0_FIFO #define IRQ_FIMD0_VSYNC EXYNOS4_IRQ_FIMD0_VSYNC #define IRQ_FIMD0_SYSTEM EXYNOS4_IRQ_FIMD0_SYSTEM diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index e178cf189d1f5b..2a222ff9d37c82 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -79,6 +79,8 @@ #define EXYNOS4_PA_KEYPAD 0x100A0000 +#define EXYNOS4_PA_CEC 0x100B0000 + #define EXYNOS4_PA_DMC0 0x10400000 #define EXYNOS4_PA_DMC1 0x10410000 @@ -276,6 +278,9 @@ #define SAMSUNG_PA_ADC1 EXYNOS4_PA_ADC1 #define SAMSUNG_PA_KEYPAD EXYNOS4_PA_KEYPAD +#define S5P_PA_HDMI_CEC EXYNOS4_PA_CEC +#define S5P_SZ_HDMI_CEC SZ_4K + /* Compatibility UART */ #define EXYNOS4_PA_UART0 0x13800000 diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h index 660809b6a883f6..1533b4871d81b0 100644 --- a/arch/arm/mach-s5pv210/include/mach/map.h +++ b/arch/arm/mach-s5pv210/include/mach/map.h @@ -48,7 +48,7 @@ #define S5PV210_PA_PCM1 0xE1200000 #define S5PV210_PA_PCM2 0xE2B00000 -#define S5PV210_PA_CEC (0xE1B00000) +#define S5PV210_PA_CEC 0xE1B00000 #define S5P_PA_CEC S5PV210_PA_CEC #define S5P_SZ_CEC SZ_4K diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index cc09ca1429b60a..ab9a64ab26f634 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c @@ -1358,7 +1358,7 @@ struct platform_device s5p_device_hdmi = { }; static struct resource s5p_cec_resources[] = { - [0] = DEFINE_RES_MEM(S5P_PA_CEC, S5P_SZ_CEC), + [0] = DEFINE_RES_MEM(S5P_PA_HDMI_CEC, S5P_SZ_HDMI_CEC), [1] = DEFINE_RES_IRQ(IRQ_CEC), }; diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index 6312492f3b49bf..1209f88660eba0 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -28,6 +28,10 @@ struct s5p_platform_cec { #include "s5p_tvout_common_lib.h" #include "hw_if/hw_if.h" +MODULE_AUTHOR("KyungHwan Kim "); +MODULE_DESCRIPTION("Samsung S5P CEC driver"); +MODULE_LICENSE("GPL"); + #define CEC_IOC_MAGIC 'c' #define CEC_IOC_SETLADDR _IOW(CEC_IOC_MAGIC, 0, unsigned int) @@ -347,17 +351,36 @@ static int s5p_cec_resume(struct platform_device *dev) #define s5p_cec_resume NULL #endif +static struct platform_device_id hdmi_driver_types[] = { + { + .name = "s5pv210-hdmi", + }, { + .name = "exynos4-hdmi", + }, { + /* end node */ + } +}; + static struct platform_driver s5p_cec_driver = { .probe = s5p_cec_probe, .remove = s5p_cec_remove, + //.id_table = hdmi_driver_types, // Shouldn't be necessary .suspend = s5p_cec_suspend, .resume = s5p_cec_resume, .driver = { - .name = "s5p-tvout-cec", + .name = "s5p-cec", .owner = THIS_MODULE, }, }; +#if 0 + + // The rest of the modules in s5p-tv do this, but it currently results in: + // [315031.925000] s5p_cec: Unknown symbol platform_driver_unregister (err 0) + module_platform_driver(s5p_cec_driver); + +#else + static int __init s5p_cec_init(void) { printk(KERN_INFO "S5P CEC for TVOUT Driver, Copyright (c) 2011 Samsung Electronics Co., LTD.\n"); @@ -373,7 +396,4 @@ static void __exit s5p_cec_exit(void) module_init(s5p_cec_init); module_exit(s5p_cec_exit); - -MODULE_AUTHOR("KyungHwan Kim "); -MODULE_DESCRIPTION("Samsung S5P CEC driver"); -MODULE_LICENSE("GPL"); +#endif From fa801119a5c9499cdc1b40261eea9728dcc1f59f Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 13:40:03 +0200 Subject: [PATCH 08/30] fixup readme --- README | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README b/README index ec7b0ee04e2e9b..bb9fabdf078da7 100644 --- a/README +++ b/README @@ -10,11 +10,12 @@ Status: TODO: Make it do something - Look at the latest android kernel sources http://dn.odroid.com/Android_Alpha_4.0.3/BSP/ - Cleanup this tree, so it becomes a minimal diff upon hardkernel's 3.8 tree + Look at the latest android kernel sources + http://dn.odroid.com/Android_Alpha_4.0.3/BSP/ + Cleanup this tree, so it becomes a nice diff upon hardkernel's 3.8 tree -================================================================================================= +================================================================================ Linux kernel release 3.x From d6aee2ddafe07cdd7886336b6db839a3a8569767 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 14:47:03 +0200 Subject: [PATCH 09/30] adapt file-organization to the rest of s5p --- drivers/media/platform/s5p-tv/Makefile | 2 +- drivers/media/platform/s5p-tv/cec_drv.c | 11 +- .../platform/s5p-tv/{hw_if/cec.c => cec_hw.c} | 7 +- drivers/media/platform/s5p-tv/cec_hw.h | 68 ++ drivers/media/platform/s5p-tv/hw_if/hw_if.h | 651 ------------------ .../platform/s5p-tv/{hw_if => }/regs-cec.h | 0 .../platform/s5p-tv/s5p_tvout_common_lib.c | 99 --- .../platform/s5p-tv/s5p_tvout_common_lib.h | 187 ----- 8 files changed, 81 insertions(+), 944 deletions(-) rename drivers/media/platform/s5p-tv/{hw_if/cec.c => cec_hw.c} (97%) create mode 100644 drivers/media/platform/s5p-tv/cec_hw.h delete mode 100644 drivers/media/platform/s5p-tv/hw_if/hw_if.h rename drivers/media/platform/s5p-tv/{hw_if => }/regs-cec.h (100%) delete mode 100644 drivers/media/platform/s5p-tv/s5p_tvout_common_lib.c delete mode 100644 drivers/media/platform/s5p-tv/s5p_tvout_common_lib.h diff --git a/drivers/media/platform/s5p-tv/Makefile b/drivers/media/platform/s5p-tv/Makefile index 10231b74abb43b..375806412df0a6 100644 --- a/drivers/media/platform/s5p-tv/Makefile +++ b/drivers/media/platform/s5p-tv/Makefile @@ -17,7 +17,7 @@ s5p-hdmi-$(CONFIG_CPU_EXYNOS4210) += hdmi_drv.o s5p-hdmi-$(CONFIG_SOC_EXYNOS4412) += hdmi_v14_drv.o obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMI_CEC) += s5p-cec.o -s5p-cec-y += cec_drv.o hw_if/cec.o +s5p-cec-y += cec_drv.o cec_hw.o obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SDO) += s5p-sdo.o s5p-sdo-y += sdo_drv.o diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index 1209f88660eba0..9ee7fa721bc3f3 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -18,6 +18,7 @@ #include #include #include +#include //#include "../../../arch/arm/plat-samsung/include/plat/tvout.h" struct s5p_platform_cec { @@ -25,8 +26,9 @@ struct s5p_platform_cec { }; -#include "s5p_tvout_common_lib.h" -#include "hw_if/hw_if.h" +//#include "s5p_tvout_common_lib.h" +//#include "hw_if/hw_if.h" +#include "cec_hw.h" MODULE_AUTHOR("KyungHwan Kim "); MODULE_DESCRIPTION("Samsung S5P CEC driver"); @@ -351,6 +353,7 @@ static int s5p_cec_resume(struct platform_device *dev) #define s5p_cec_resume NULL #endif +#if 0 static struct platform_device_id hdmi_driver_types[] = { { .name = "s5pv210-hdmi", @@ -360,6 +363,7 @@ static struct platform_device_id hdmi_driver_types[] = { /* end node */ } }; +#endif static struct platform_driver s5p_cec_driver = { .probe = s5p_cec_probe, @@ -384,6 +388,9 @@ static struct platform_driver s5p_cec_driver = { static int __init s5p_cec_init(void) { printk(KERN_INFO "S5P CEC for TVOUT Driver, Copyright (c) 2011 Samsung Electronics Co., LTD.\n"); + + request_module("s5p-hdmi"); + return platform_driver_register(&s5p_cec_driver); } diff --git a/drivers/media/platform/s5p-tv/hw_if/cec.c b/drivers/media/platform/s5p-tv/cec_hw.c similarity index 97% rename from drivers/media/platform/s5p-tv/hw_if/cec.c rename to drivers/media/platform/s5p-tv/cec_hw.c index 9e5677699d141f..b414e61a9f1d75 100644 --- a/drivers/media/platform/s5p-tv/hw_if/cec.c +++ b/drivers/media/platform/s5p-tv/cec_hw.c @@ -11,14 +11,13 @@ #include #include +#include -#include #include #include -#include "../s5p_tvout_common_lib.h" -#include "hw_if.h" -#include "regs-cec.h" // TODO: move to /arch/arm/plat* +#include "cec_hw.h" +#include "regs-cec.h" // somehow mach/regs-cec.h isn't picked up #define S5P_HDMI_FIN 24000000 #define CEC_DIV_RATIO 320000 diff --git a/drivers/media/platform/s5p-tv/cec_hw.h b/drivers/media/platform/s5p-tv/cec_hw.h new file mode 100644 index 00000000000000..514bf8548f61bf --- /dev/null +++ b/drivers/media/platform/s5p-tv/cec_hw.h @@ -0,0 +1,68 @@ + +#ifndef CEC_HW_H_ +#define CEC_HW_H_ + +#include + +#define to_tvout_plat(d) (to_platform_device(d)->dev.platform_data) + +#define tvout_err(fmt, ...) \ + printk(KERN_ERR "[%s] %s(): " fmt, \ + DRV_NAME, __func__, ##__VA_ARGS__) + +#ifndef tvout_dbg +#ifdef CONFIG_S5P_TVOUT_DEBUG +#define tvout_dbg(fmt, ...) \ + printk(KERN_INFO "[%s] %s(): " fmt, \ + DRV_NAME, __func__, ##__VA_ARGS__) +#else +#define tvout_dbg(fmt, ...) +#endif +#endif + + +enum cec_state { + STATE_RX, + STATE_TX, + STATE_DONE, + STATE_ERROR +}; + +struct cec_rx_struct { + spinlock_t lock; + wait_queue_head_t waitq; + atomic_t state; + u8 *buffer; + unsigned int size; +}; + +struct cec_tx_struct { + wait_queue_head_t waitq; + atomic_t state; +}; + +extern struct cec_rx_struct cec_rx_struct; +extern struct cec_tx_struct cec_tx_struct; + +void s5p_cec_set_divider(void); +void s5p_cec_enable_rx(void); +void s5p_cec_mask_rx_interrupts(void); +void s5p_cec_unmask_rx_interrupts(void); +void s5p_cec_mask_tx_interrupts(void); +void s5p_cec_unmask_tx_interrupts(void); +void s5p_cec_reset(void); +void s5p_cec_tx_reset(void); +void s5p_cec_rx_reset(void); +void s5p_cec_threshold(void); +void s5p_cec_set_tx_state(enum cec_state state); +void s5p_cec_set_rx_state(enum cec_state state); +void s5p_cec_copy_packet(char *data, size_t count); +void s5p_cec_set_addr(u32 addr); +u32 s5p_cec_get_status(void); +void s5p_clr_pending_tx(void); +void s5p_clr_pending_rx(void); +void s5p_cec_get_rx_buf(u32 size, u8 *buffer); +void s5p_cec_mem_probe(struct platform_device *pdev); + + +#endif \ No newline at end of file diff --git a/drivers/media/platform/s5p-tv/hw_if/hw_if.h b/drivers/media/platform/s5p-tv/hw_if/hw_if.h deleted file mode 100644 index b13fa54547871d..00000000000000 --- a/drivers/media/platform/s5p-tv/hw_if/hw_if.h +++ /dev/null @@ -1,651 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Header file for interface of Samsung TVOUT-related hardware - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __S5P_TVOUT_HW_IF_H_ -#define __S5P_TVOUT_HW_IF_H_ __FILE__ - -/* - * This file includes declarations for external functions of - * Samsung TVOUT-related hardware. So only external functions - * to be used by higher layer must exist in this file. - * - * Higher layer must use only the declarations included in this file. - */ - -#include -#include - -#include "../s5p_tvout_common_lib.h" - -/* Common */ - -enum s5p_tvout_endian { - TVOUT_LITTLE_ENDIAN = 0, - TVOUT_BIG_ENDIAN = 1 -}; - -/* for MIXER */ - -enum s5p_mixer_layer { - MIXER_VIDEO_LAYER = 2, - MIXER_GPR0_LAYER = 0, - MIXER_GPR1_LAYER = 1 -}; - -enum s5p_mixer_bg_color_num { - MIXER_BG_COLOR_0 = 0, - MIXER_BG_COLOR_1 = 1, - MIXER_BG_COLOR_2 = 2 -}; - -enum s5p_mixer_color_fmt { - MIXER_RGB565 = 4, - MIXER_RGB1555 = 5, - MIXER_RGB4444 = 6, - MIXER_RGB8888 = 7 -}; - -enum s5p_mixer_csc_type { - MIXER_CSC_601_LR, - MIXER_CSC_601_FR, - MIXER_CSC_709_LR, - MIXER_CSC_709_FR -}; - -enum s5p_mixer_rgb { - MIXER_RGB601_0_255, - MIXER_RGB601_16_235, - MIXER_RGB709_0_255, - MIXER_RGB709_16_235 -}; - -enum s5p_mixer_out_type { - MIXER_YUV444, - MIXER_RGB888 -}; - -extern int s5p_mixer_set_show(enum s5p_mixer_layer layer, bool show); -extern int s5p_mixer_set_priority(enum s5p_mixer_layer layer, u32 priority); -extern void s5p_mixer_set_pre_mul_mode(enum s5p_mixer_layer layer, bool enable); -extern int s5p_mixer_set_pixel_blend(enum s5p_mixer_layer layer, bool enable); -extern int s5p_mixer_set_layer_blend(enum s5p_mixer_layer layer, bool enable); -extern int s5p_mixer_set_alpha(enum s5p_mixer_layer layer, u32 alpha); -extern int s5p_mixer_set_grp_base_address(enum s5p_mixer_layer layer, - u32 baseaddr); -extern int s5p_mixer_set_grp_layer_dst_pos(enum s5p_mixer_layer layer, - u32 dst_offs_x, u32 dst_offs_y); -extern int s5p_mixer_set_grp_layer_src_pos(enum s5p_mixer_layer layer, - u32 span, u32 width, u32 height, - u32 src_offs_x, u32 src_offs_y); -extern void s5p_mixer_set_bg_color(enum s5p_mixer_bg_color_num colornum, - u32 color_y, u32 color_cb, u32 color_cr); -extern void s5p_mixer_init_status_reg(enum s5p_mixer_burst_mode burst, - enum s5p_tvout_endian endian); -extern int s5p_mixer_init_display_mode(enum s5p_tvout_disp_mode mode, - enum s5p_tvout_o_mode output_mode); -extern void s5p_mixer_scaling(enum s5p_mixer_layer layer, - struct s5ptvfb_user_scaling scaling); -extern void s5p_mixer_set_color_format(enum s5p_mixer_layer layer, - enum s5p_mixer_color_fmt format); -extern void s5p_mixer_set_chroma_key(enum s5p_mixer_layer layer, - bool enabled, u32 key); -extern void s5p_mixer_init_bg_dither_enable(bool cr_dither_enable, - bool cdither_enable, - bool y_dither_enable); -extern void s5p_mixer_init_csc_coef_default(enum s5p_mixer_csc_type csc_type); -extern void s5p_mixer_start(void); -extern void s5p_mixer_stop(void); -extern void s5p_mixer_set_underflow_int_enable(enum s5p_mixer_layer layer, - bool en); -extern void s5p_mixer_set_vsync_interrupt(bool); -extern void s5p_mixer_clear_pend_all(void); -extern irqreturn_t s5p_mixer_irq(int irq, void *dev_id); -extern void s5p_mixer_init(void __iomem *addr); - -/* for HDMI */ - -#define HDMI_MASK_8(x) ((x) & 0xFF) -#define HDMI_MASK_16(x) (((x) >> 8) & 0xFF) -#define HDMI_MASK_24(x) (((x) >> 16) & 0xFF) -#define HDMI_MASK_32(x) (((x) >> 24) & 0xFF) - -#define hdmi_write_16(x, y) \ - do { \ - writeb(HDMI_MASK_8(x), y); \ - writeb(HDMI_MASK_16(x), y + 4); \ - } while (0); - -#define hdmi_write_24(x, y) \ - do { \ - writeb(HDMI_MASK_8(x), y); \ - writeb(HDMI_MASK_16(x), y + 4); \ - writeb(HDMI_MASK_24(x), y + 8); \ - } while (0); - -#define hdmi_write_32(x, y) \ - do { \ - writeb(HDMI_MASK_8(x), y); \ - writeb(HDMI_MASK_16(x), y + 4); \ - writeb(HDMI_MASK_24(x), y + 8); \ - writeb(HDMI_MASK_32(x), y + 12); \ - } while (0); - -#define hdmi_write_l(buff, base, start, count) \ - do { \ - u8 *ptr = buff; \ - int i = 0; \ - int a = start; \ - do { \ - writeb(ptr[i], base + a); \ - a += 4; \ - i++; \ - } while (i <= (count - 1)); \ - } while (0); - -#define hdmi_read_l(buff, base, start, count) \ - do { \ - u8 *ptr = buff; \ - int i = 0; \ - int a = start; \ - do { \ - ptr[i] = readb(base + a); \ - a += 4; \ - i++; \ - } while (i <= (count - 1)); \ - } while (0); - -#define hdmi_bit_set(en, reg, val) \ - do { \ - if (en) \ - reg |= val; \ - else \ - reg &= ~val; \ - } while (0); - -enum s5p_hdmi_transmit { - HDMI_DO_NOT_TANS, - HDMI_TRANS_ONCE, - HDMI_TRANS_EVERY_SYNC, -}; - -enum s5p_tvout_audio_codec_type { - PCM = 1, - AC3, - MP3, - WMA -}; - -enum s5p_hdmi_infoframe_type { - HDMI_VSI_INFO = 0x81, - HDMI_AVI_INFO, - HDMI_SPD_INFO, - HDMI_AUI_INFO, - HDMI_MPG_INFO, -}; - -enum s5p_hdmi_color_depth { - HDMI_CD_48, - HDMI_CD_36, - HDMI_CD_30, - HDMI_CD_24 -}; - -enum s5p_hdmi_interrrupt { - HDMI_IRQ_PIN_POLAR_CTL = 7, - HDMI_IRQ_GLOBAL = 6, - HDMI_IRQ_I2S = 5, - HDMI_IRQ_CEC = 4, - HDMI_IRQ_HPD_PLUG = 3, - HDMI_IRQ_HPD_UNPLUG = 2, - HDMI_IRQ_SPDIF = 1, - HDMI_IRQ_HDCP = 0 -}; - -enum phy_freq { - ePHY_FREQ_25_200, - ePHY_FREQ_25_175, - ePHY_FREQ_27, - ePHY_FREQ_27_027, - ePHY_FREQ_54, - ePHY_FREQ_54_054, - ePHY_FREQ_74_250, - ePHY_FREQ_74_176, - ePHY_FREQ_148_500, - ePHY_FREQ_148_352, - ePHY_FREQ_108_108, - ePHY_FREQ_72, - ePHY_FREQ_25, - ePHY_FREQ_65, - ePHY_FREQ_108, - ePHY_FREQ_162 -}; - -struct s5p_hdmi_infoframe { - enum s5p_hdmi_infoframe_type type; - u8 version; - u8 length; -}; - -struct s5p_hdmi_o_trans { - enum s5p_hdmi_transmit avi; - enum s5p_hdmi_transmit mpg; - enum s5p_hdmi_transmit spd; - enum s5p_hdmi_transmit gcp; - enum s5p_hdmi_transmit gmp; - enum s5p_hdmi_transmit isrc; - enum s5p_hdmi_transmit acp; - enum s5p_hdmi_transmit aui; - enum s5p_hdmi_transmit acr; -}; - -struct s5p_hdmi_o_reg { - u8 pxl_fmt; - u8 preemble; - u8 mode; - u8 pxl_limit; - u8 dvi; -}; - -struct s5p_hdmi_v_frame { - u8 vic; - u8 vic_16_9; - u8 repetition; - u8 polarity; - u8 i_p; - - u16 h_active; - u16 v_active; - - u16 h_total; - u16 h_blank; - - u16 v_total; - u16 v_blank; - - enum phy_freq pixel_clock; -}; - -struct s5p_hdmi_tg_sync { - u16 begin; - u16 end; -}; - -struct s5p_hdmi_v_format { - struct s5p_hdmi_v_frame frame; - - struct s5p_hdmi_tg_sync h_sync; - struct s5p_hdmi_tg_sync v_sync_top; - struct s5p_hdmi_tg_sync v_sync_bottom; - struct s5p_hdmi_tg_sync v_sync_h_pos; - - struct s5p_hdmi_tg_sync v_blank_f; - - u8 mhl_hsync; - u8 mhl_vsync; -}; - -extern int s5p_hdmi_phy_power(bool on); -extern s32 s5p_hdmi_phy_config(enum phy_freq freq, - enum s5p_hdmi_color_depth cd); - -extern void s5p_hdmi_set_gcp(enum s5p_hdmi_color_depth depth, u8 *gcp); -extern void s5p_hdmi_reg_acr(u8 *acr); -extern void s5p_hdmi_reg_asp(u8 *asp); -extern void s5p_hdmi_reg_gcp(u8 i_p, u8 *gcp); -extern void s5p_hdmi_reg_acp(u8 *header, u8 *acp); -extern void s5p_hdmi_reg_isrc(u8 *isrc1, u8 *isrc2); -extern void s5p_hdmi_reg_gmp(u8 *gmp); -extern void s5p_hdmi_reg_infoframe(struct s5p_hdmi_infoframe *info, u8 *data); -extern void s5p_hdmi_reg_tg(struct s5p_hdmi_v_frame *frame); -extern void s5p_hdmi_reg_v_timing(struct s5p_hdmi_v_format *v); -extern void s5p_hdmi_reg_bluescreen_clr(u8 cb_b, u8 y_g, u8 cr_r); -extern void s5p_hdmi_reg_bluescreen(bool en); -extern void s5p_hdmi_reg_clr_range(u8 y_min, u8 y_max, u8 c_min, u8 c_max); -extern void s5p_hdmi_reg_tg_cmd(bool time, bool bt656, bool tg); -extern void s5p_hdmi_reg_enable(bool en); -extern u8 s5p_hdmi_reg_intc_status(void); -extern u8 s5p_hdmi_reg_intc_get_enabled(void); -extern void s5p_hdmi_reg_intc_clear_pending(enum s5p_hdmi_interrrupt intr); -extern void s5p_hdmi_reg_sw_hpd_enable(bool enable); -extern void s5p_hdmi_reg_set_hpd_onoff(bool on_off); -extern u8 s5p_hdmi_reg_get_hpd_status(void); -extern void s5p_hdmi_reg_hpd_gen(void); -extern int s5p_hdmi_reg_intc_set_isr(irqreturn_t (*isr)(int, void *), u8 num); -extern void s5p_hdmi_reg_intc_enable(enum s5p_hdmi_interrrupt intr, u8 en); -extern void s5p_hdmi_reg_audio_enable(u8 en); -extern int s5p_hdmi_audio_init(enum s5p_tvout_audio_codec_type audio_codec, - u32 sample_rate, u32 bits, u32 frame_size_code); -extern irqreturn_t s5p_hdmi_irq(int irq, void *dev_id); -extern void s5p_hdmi_init(void __iomem *hdmi_addr, - void __iomem *hdmi_phy_addr); -extern void s5p_hdmi_reg_output(struct s5p_hdmi_o_reg *reg); -extern void s5p_hdmi_reg_packet_trans(struct s5p_hdmi_o_trans *trans); -extern void s5p_hdmi_reg_mute(bool en); - -extern void __iomem *hdmi_base; - -/* for SDO */ - -enum s5p_sdo_level { - SDO_LEVEL_0IRE, - SDO_LEVEL_75IRE -}; - -enum s5p_sdo_vsync_ratio { - SDO_VTOS_RATIO_10_4, - SDO_VTOS_RATIO_7_3 -}; - -enum s5p_sdo_order { - SDO_O_ORDER_COMPONENT_RGB_PRYPB, - SDO_O_ORDER_COMPONENT_RBG_PRPBY, - SDO_O_ORDER_COMPONENT_BGR_PBYPR, - SDO_O_ORDER_COMPONENT_BRG_PBPRY, - SDO_O_ORDER_COMPONENT_GRB_YPRPB, - SDO_O_ORDER_COMPONENT_GBR_YPBPR, - SDO_O_ORDER_COMPOSITE_CVBS_Y_C, - SDO_O_ORDER_COMPOSITE_CVBS_C_Y, - SDO_O_ORDER_COMPOSITE_Y_C_CVBS, - SDO_O_ORDER_COMPOSITE_Y_CVBS_C, - SDO_O_ORDER_COMPOSITE_C_CVBS_Y, - SDO_O_ORDER_COMPOSITE_C_Y_CVBS -}; - -enum s5p_sdo_sync_sig_pin { - SDO_SYNC_SIG_NO, - SDO_SYNC_SIG_YG, - SDO_SYNC_SIG_ALL -}; - -enum s5p_sdo_closed_caption_type { - SDO_NO_INS, - SDO_INS_1, - SDO_INS_2, - SDO_INS_OTHERS -}; - -enum s5p_sdo_525_copy_permit { - SDO_525_COPY_PERMIT, - SDO_525_ONECOPY_PERMIT, - SDO_525_NOCOPY_PERMIT -}; - -enum s5p_sdo_525_mv_psp { - SDO_525_MV_PSP_OFF, - SDO_525_MV_PSP_ON_2LINE_BURST, - SDO_525_MV_PSP_ON_BURST_OFF, - SDO_525_MV_PSP_ON_4LINE_BURST, -}; - -enum s5p_sdo_525_copy_info { - SDO_525_COPY_INFO, - SDO_525_DEFAULT, -}; - -enum s5p_sdo_525_aspect_ratio { - SDO_525_4_3_NORMAL, - SDO_525_16_9_ANAMORPIC, - SDO_525_4_3_LETTERBOX -}; - -enum s5p_sdo_625_subtitles { - SDO_625_NO_OPEN_SUBTITLES, - SDO_625_INACT_OPEN_SUBTITLES, - SDO_625_OUTACT_OPEN_SUBTITLES -}; - -enum s5p_sdo_625_camera_film { - SDO_625_CAMERA, - SDO_625_FILM -}; - -enum s5p_sdo_625_color_encoding { - SDO_625_NORMAL_PAL, - SDO_625_MOTION_ADAPTIVE_COLORPLUS -}; - -enum s5p_sdo_625_aspect_ratio { - SDO_625_4_3_FULL_576, - SDO_625_14_9_LETTERBOX_CENTER_504, - SDO_625_14_9_LETTERBOX_TOP_504, - SDO_625_16_9_LETTERBOX_CENTER_430, - SDO_625_16_9_LETTERBOX_TOP_430, - SDO_625_16_9_LETTERBOX_CENTER, - SDO_625_14_9_FULL_CENTER_576, - SDO_625_16_9_ANAMORPIC_576 -}; - -struct s5p_sdo_cvbs_compensation { - bool cvbs_color_compen; - u32 y_lower_mid; - u32 y_bottom; - u32 y_top; - u32 y_upper_mid; - u32 radius; -}; - -struct s5p_sdo_bright_hue_saturation { - bool bright_hue_sat_adj; - u32 gain_brightness; - u32 offset_brightness; - u32 gain0_cb_hue_sat; - u32 gain1_cb_hue_sat; - u32 gain0_cr_hue_sat; - u32 gain1_cr_hue_sat; - u32 offset_cb_hue_sat; - u32 offset_cr_hue_sat; -}; - -struct s5p_sdo_525_data { - bool analog_on; - enum s5p_sdo_525_copy_permit copy_permit; - enum s5p_sdo_525_mv_psp mv_psp; - enum s5p_sdo_525_copy_info copy_info; - enum s5p_sdo_525_aspect_ratio display_ratio; -}; - -struct s5p_sdo_625_data { - bool surround_sound; - bool copyright; - bool copy_protection; - bool text_subtitles; - enum s5p_sdo_625_subtitles open_subtitles; - enum s5p_sdo_625_camera_film camera_film; - enum s5p_sdo_625_color_encoding color_encoding; - bool helper_signal; - enum s5p_sdo_625_aspect_ratio display_ratio; -}; - -extern int s5p_sdo_set_video_scale_cfg(enum s5p_sdo_level composite_level, - enum s5p_sdo_vsync_ratio composite_ratio); -extern int s5p_sdo_set_vbi(bool wss_cvbs, - enum s5p_sdo_closed_caption_type caption_cvbs); -extern void s5p_sdo_set_offset_gain(u32 offset, u32 gain); -extern void s5p_sdo_set_delay(u32 delay_y, u32 offset_video_start, - u32 offset_video_end); -extern void s5p_sdo_set_schlock(bool color_sucarrier_pha_adj); -extern void s5p_sdo_set_brightness_hue_saturation(struct s5p_sdo_bright_hue_saturation bri_hue_sat); -extern void s5p_sdo_set_cvbs_color_compensation(struct s5p_sdo_cvbs_compensation cvbs_comp); -extern void s5p_sdo_set_component_porch(u32 back_525, u32 front_525, - u32 back_625, u32 front_625); -extern void s5p_sdo_set_ch_xtalk_cancel_coef(u32 coeff2, u32 coeff1); -extern void s5p_sdo_set_closed_caption(u32 display_cc, u32 non_display_cc); - -extern int s5p_sdo_set_wss525_data(struct s5p_sdo_525_data wss525); -extern int s5p_sdo_set_wss625_data(struct s5p_sdo_625_data wss625); -extern int s5p_sdo_set_cgmsa525_data(struct s5p_sdo_525_data cgmsa525); -extern int s5p_sdo_set_cgmsa625_data(struct s5p_sdo_625_data cgmsa625); -extern int s5p_sdo_set_display_mode(enum s5p_tvout_disp_mode disp_mode, - enum s5p_sdo_order order); -extern void s5p_sdo_clock_on(bool on); -extern void s5p_sdo_dac_on(bool on); -extern void s5p_sdo_sw_reset(bool active); -extern void s5p_sdo_set_interrupt_enable(bool vsync_intc_en); -extern void s5p_sdo_clear_interrupt_pending(void); -extern void s5p_sdo_init(void __iomem *addr); - -/* for VP */ - -enum s5p_vp_field { - VP_TOP_FIELD, - VP_BOTTOM_FIELD -}; - -enum s5p_vp_line_eq { - VP_LINE_EQ_0, - VP_LINE_EQ_1, - VP_LINE_EQ_2, - VP_LINE_EQ_3, - VP_LINE_EQ_4, - VP_LINE_EQ_5, - VP_LINE_EQ_6, - VP_LINE_EQ_7, - VP_LINE_EQ_DEFAULT -}; - -enum s5p_vp_mem_type { - VP_YUV420_NV12, - VP_YUV420_NV21 -}; - -enum s5p_vp_mem_mode { - VP_LINEAR_MODE, - VP_2D_TILE_MODE -}; - -enum s5p_vp_chroma_expansion { - VP_C_TOP, - VP_C_TOP_BOTTOM -}; - -enum s5p_vp_pxl_rate { - VP_PXL_PER_RATE_1_1, - VP_PXL_PER_RATE_1_2, - VP_PXL_PER_RATE_1_3, - VP_PXL_PER_RATE_1_4 -}; - -enum s5p_vp_sharpness_control { - VP_SHARPNESS_NO, - VP_SHARPNESS_MIN, - VP_SHARPNESS_MOD, - VP_SHARPNESS_MAX -}; - -enum s5p_vp_csc_type { - VP_CSC_SD_HD, - VP_CSC_HD_SD -}; - -enum s5p_vp_csc_coeff { - VP_CSC_Y2Y_COEF, - VP_CSC_CB2Y_COEF, - VP_CSC_CR2Y_COEF, - VP_CSC_Y2CB_COEF, - VP_CSC_CB2CB_COEF, - VP_CSC_CR2CB_COEF, - VP_CSC_Y2CR_COEF, - VP_CSC_CB2CR_COEF, - VP_CSC_CR2CR_COEF -}; - - -extern void s5p_vp_set_poly_filter_coef_default(u32 src_width, u32 src_height, - u32 dst_width, u32 dst_height, - bool ipc_2d); -extern void s5p_vp_set_field_id(enum s5p_vp_field mode); -extern int s5p_vp_set_top_field_address(u32 top_y_addr, u32 top_c_addr); -extern int s5p_vp_set_bottom_field_address(u32 bottom_y_addr, - u32 bottom_c_addr); -extern int s5p_vp_set_img_size(u32 img_width, u32 img_height); -extern void s5p_vp_set_src_position(u32 src_off_x, u32 src_x_fract_step, - u32 src_off_y); -extern void s5p_vp_set_dest_position(u32 dst_off_x, u32 dst_off_y); -extern void s5p_vp_set_src_dest_size(u32 src_width, u32 src_height, - u32 dst_width, u32 dst_height, - bool ipc_2d); -extern void s5p_vp_set_op_mode(bool line_skip, enum s5p_vp_mem_type mem_type, - enum s5p_vp_mem_mode mem_mode, - enum s5p_vp_chroma_expansion chroma_exp, - bool auto_toggling); -extern void s5p_vp_set_pixel_rate_control(enum s5p_vp_pxl_rate rate); -extern void s5p_vp_set_endian(enum s5p_tvout_endian endian); -extern void s5p_vp_set_bypass_post_process(bool bypass); -extern void s5p_vp_set_saturation(u32 sat); -extern void s5p_vp_set_sharpness(u32 th_h_noise, - enum s5p_vp_sharpness_control sharpness); -extern void s5p_vp_set_brightness_contrast(u16 b, u8 c); -extern void s5p_vp_set_brightness_offset(u32 offset); -extern int s5p_vp_set_brightness_contrast_control(enum s5p_vp_line_eq eq_num, - u32 intc, u32 slope); -extern void s5p_vp_set_csc_control(bool sub_y_offset_en, bool csc_en); -extern int s5p_vp_set_csc_coef(enum s5p_vp_csc_coeff csc_coeff, u32 coeff); -extern int s5p_vp_set_csc_coef_default(enum s5p_vp_csc_type csc_type); -extern int s5p_vp_update(void); -extern int s5p_vp_get_update_status(void); -extern void s5p_vp_sw_reset(void); -extern int s5p_vp_start(void); -extern int s5p_vp_stop(void); -extern void s5p_vp_init(void __iomem *addr); - -/* for CEC */ - -enum cec_state { - STATE_RX, - STATE_TX, - STATE_DONE, - STATE_ERROR -}; - -struct cec_rx_struct { - spinlock_t lock; - wait_queue_head_t waitq; - atomic_t state; - u8 *buffer; - unsigned int size; -}; - -struct cec_tx_struct { - wait_queue_head_t waitq; - atomic_t state; -}; - -extern struct cec_rx_struct cec_rx_struct; -extern struct cec_tx_struct cec_tx_struct; - -void s5p_cec_set_divider(void); -void s5p_cec_enable_rx(void); -void s5p_cec_mask_rx_interrupts(void); -void s5p_cec_unmask_rx_interrupts(void); -void s5p_cec_mask_tx_interrupts(void); -void s5p_cec_unmask_tx_interrupts(void); -void s5p_cec_reset(void); -void s5p_cec_tx_reset(void); -void s5p_cec_rx_reset(void); -void s5p_cec_threshold(void); -void s5p_cec_set_tx_state(enum cec_state state); -void s5p_cec_set_rx_state(enum cec_state state); -void s5p_cec_copy_packet(char *data, size_t count); -void s5p_cec_set_addr(u32 addr); -u32 s5p_cec_get_status(void); -void s5p_clr_pending_tx(void); -void s5p_clr_pending_rx(void); -void s5p_cec_get_rx_buf(u32 size, u8 *buffer); -void s5p_cec_mem_probe(struct platform_device *pdev); - -/* for HDCP */ - -extern int s5p_hdcp_encrypt_stop(bool on); -extern int __init s5p_hdcp_init(void); -extern int s5p_hdcp_start(void); -extern int s5p_hdcp_stop(void); - -#endif /* __S5P_TVOUT_HW_IF_H_ */ diff --git a/drivers/media/platform/s5p-tv/hw_if/regs-cec.h b/drivers/media/platform/s5p-tv/regs-cec.h similarity index 100% rename from drivers/media/platform/s5p-tv/hw_if/regs-cec.h rename to drivers/media/platform/s5p-tv/regs-cec.h diff --git a/drivers/media/platform/s5p-tv/s5p_tvout_common_lib.c b/drivers/media/platform/s5p-tv/s5p_tvout_common_lib.c deleted file mode 100644 index 550efe041f47cc..00000000000000 --- a/drivers/media/platform/s5p-tv/s5p_tvout_common_lib.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Common library for SAMSUNG S5P TVOUT driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include -#include - -#include - -#include "s5p_tvout_common_lib.h" - -int s5p_tvout_map_resource_mem(struct platform_device *pdev, char *name, - void __iomem **base, struct resource **res) -{ - size_t size; - void __iomem *tmp_base; - struct resource *tmp_res; - - tmp_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); - - if (!tmp_res) - goto not_found; - - size = resource_size(tmp_res); - - tmp_res = request_mem_region(tmp_res->start, size, tmp_res->name); - - if (!tmp_res) { - tvout_err("%s: fail to get memory region\n", __func__); - goto err_on_request_mem_region; - } - - tmp_base = ioremap(tmp_res->start, size); - - if (!tmp_base) { - tvout_err("%s: fail to ioremap address region\n", __func__); - goto err_on_ioremap; - } - - *res = tmp_res; - *base = tmp_base; - return 0; - -err_on_ioremap: - release_resource(tmp_res); - kfree(tmp_res); - -err_on_request_mem_region: - return -ENXIO; - -not_found: - tvout_err("%s: fail to get IORESOURCE_MEM for %s\n", __func__, name); - return -ENODEV; -} - -void s5p_tvout_unmap_resource_mem(void __iomem *base, struct resource *res) -{ - if (!base) - iounmap(base); - - if (res != NULL) { - release_resource(res); - kfree(res); - } -} - -/* Libraries for runtime PM */ - -static struct device *s5p_tvout_dev; - -void s5p_tvout_pm_runtime_enable(struct device *dev) -{ - pm_runtime_enable(dev); - - s5p_tvout_dev = dev; -} - -void s5p_tvout_pm_runtime_disable(struct device *dev) -{ - pm_runtime_disable(dev); -} - -void s5p_tvout_pm_runtime_get(void) -{ - pm_runtime_get_sync(s5p_tvout_dev); -} - -void s5p_tvout_pm_runtime_put(void) -{ - pm_runtime_put_sync(s5p_tvout_dev); -} diff --git a/drivers/media/platform/s5p-tv/s5p_tvout_common_lib.h b/drivers/media/platform/s5p-tv/s5p_tvout_common_lib.h deleted file mode 100644 index 7e87a03d142d77..00000000000000 --- a/drivers/media/platform/s5p-tv/s5p_tvout_common_lib.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Header file of common library for SAMSUNG S5P TVOUT driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __S5P_TVOUT_COMMON_LIB_H_ -#define __S5P_TVOUT_COMMON_LIB_H_ __FILE__ - -#include -#include -#include -#include - -/* - * This file includes declarations for TVOUT driver's common library. - * All files in TVOUT driver can access function or definition in this file. - */ - -#define DRV_NAME "S5P-TVOUT" - -#define tvout_err(fmt, ...) \ - printk(KERN_ERR "[%s] %s(): " fmt, \ - DRV_NAME, __func__, ##__VA_ARGS__) - -#ifndef tvout_dbg -#ifdef CONFIG_S5P_TVOUT_DEBUG -#define tvout_dbg(fmt, ...) \ - printk(KERN_INFO "[%s] %s(): " fmt, \ - DRV_NAME, __func__, ##__VA_ARGS__) -#else -#define tvout_dbg(fmt, ...) -#endif -#endif - -#define S5PTV_FB_CNT 2 -#define HDMI_START_NUM 0x1000 - -#define to_tvout_plat(d) (to_platform_device(d)->dev.platform_data) - -enum s5p_tvout_disp_mode { - TVOUT_NTSC_M, - TVOUT_PAL_BDGHI, - TVOUT_PAL_M, - TVOUT_PAL_N, - TVOUT_PAL_NC, - TVOUT_PAL_60, - TVOUT_NTSC_443, - - TVOUT_480P_60_16_9 = HDMI_START_NUM, - TVOUT_480P_60_4_3, - TVOUT_480P_59, - - TVOUT_576P_50_16_9, - TVOUT_576P_50_4_3, - - TVOUT_720P_60, - TVOUT_720P_50, - TVOUT_720P_59, - - TVOUT_1080P_60, - TVOUT_1080P_50, - TVOUT_1080P_59, - TVOUT_1080P_30, - - TVOUT_1080I_60, - TVOUT_1080I_50, - TVOUT_1080I_59, - TVOUT_INIT_DISP_VALUE -}; - -enum s5p_tvout_o_mode { - TVOUT_COMPOSITE, - TVOUT_HDMI, - TVOUT_HDMI_RGB, - TVOUT_DVI, - TVOUT_INIT_O_VALUE -}; - -enum s5p_mixer_burst_mode { - MIXER_BURST_8, - MIXER_BURST_16, -}; - -enum s5ptvfb_data_path_t { - DATA_PATH_FIFO, - DATA_PATH_DMA, -}; - -enum s5ptvfb_alpha_t { - LAYER_BLENDING, - PIXEL_BLENDING, - NONE_BLENDING, -}; - -enum s5ptvfb_ver_scaling_t { - VERTICAL_X1, - VERTICAL_X2, -}; - -enum s5ptvfb_hor_scaling_t { - HORIZONTAL_X1, - HORIZONTAL_X2, -}; - -struct s5ptvfb_alpha { - enum s5ptvfb_alpha_t mode; - int channel; - unsigned int value; -}; - -struct s5ptvfb_chroma { - int enabled; - unsigned int key; -}; - -struct s5ptvfb_user_window { - int x; - int y; -}; - -struct s5ptvfb_user_plane_alpha { - int channel; - unsigned char alpha; -}; - -struct s5ptvfb_user_chroma { - int enabled; - unsigned char red; - unsigned char green; - unsigned char blue; -}; - -struct s5ptvfb_user_scaling { - enum s5ptvfb_ver_scaling_t ver; - enum s5ptvfb_hor_scaling_t hor; -}; - -struct s5p_tvout_status { - struct clk *i2c_phy_clk; - struct clk *sclk_hdmiphy; - struct clk *sclk_pixel; - struct clk *sclk_dac; - struct clk *sclk_hdmi; -}; - -struct reg_mem_info { - char *name; - struct resource *res; - void __iomem *base; -}; - -struct irq_info { - char *name; - irq_handler_t handler; - int no; -}; - -struct s5p_tvout_clk_info { - char *name; - struct clk *ptr; -}; - -extern struct s5p_tvout_status s5ptv_status; - -extern int s5p_tvout_vcm_create_unified(void); -extern int s5p_tvout_vcm_init(void); -extern void s5p_tvout_vcm_activate(void); -extern void s5p_tvout_vcm_deactivate(void); - -extern int s5p_tvout_map_resource_mem(struct platform_device *pdev, - char *name, void __iomem **base, - struct resource **res); -extern void s5p_tvout_unmap_resource_mem(void __iomem *base, - struct resource *res); - -extern void s5p_tvout_pm_runtime_enable(struct device *dev); -extern void s5p_tvout_pm_runtime_disable(struct device *dev); -extern void s5p_tvout_pm_runtime_get(void); -extern void s5p_tvout_pm_runtime_put(void); - -#endif /* __S5P_TVOUT_COMMON_LIB_H_ */ From 8c06a6efbfea1e30ebea9ba5fe6a51afd4c76efd Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 15:04:58 +0200 Subject: [PATCH 10/30] some debug tracing --- drivers/media/platform/s5p-tv/cec_drv.c | 40 ++++++++++++------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index 9ee7fa721bc3f3..0bc1d932e1ba50 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -330,6 +330,7 @@ static int s5p_cec_probe(struct platform_device *pdev) static int s5p_cec_remove(struct platform_device *pdev) { int irq_num = platform_get_irq(pdev, 0); + printk(KERN_INFO "s5p_cec_remove, irq=%i\n", irq_num); free_irq(irq_num, NULL); misc_deregister(&cec_misc_device); @@ -340,11 +341,13 @@ static int s5p_cec_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int s5p_cec_suspend(struct platform_device *dev, pm_message_t state) { + printk(KERN_INFO "s5p_cec_suspend is a NOP\n"); return 0; } static int s5p_cec_resume(struct platform_device *dev) { + printk(KERN_INFO "s5p_cec_resume is a NOP\n"); return 0; } @@ -378,29 +381,24 @@ static struct platform_driver s5p_cec_driver = { }; #if 0 - - // The rest of the modules in s5p-tv do this, but it currently results in: - // [315031.925000] s5p_cec: Unknown symbol platform_driver_unregister (err 0) + // The rest of the modules in s5p-tv do this: + // It makes debugging the probe a bit trickier, so don't do this now module_platform_driver(s5p_cec_driver); - #else - -static int __init s5p_cec_init(void) -{ - printk(KERN_INFO "S5P CEC for TVOUT Driver, Copyright (c) 2011 Samsung Electronics Co., LTD.\n"); - - request_module("s5p-hdmi"); - - return platform_driver_register(&s5p_cec_driver); -} + static int __init s5p_cec_init(void) + { + printk(KERN_INFO "S5P CEC for TVOUT Driver, Copyright (c) 2011 Samsung Electronics Co., LTD.\n"); + request_module("s5p-hdmi"); + return platform_driver_register(&s5p_cec_driver); + } -static void __exit s5p_cec_exit(void) -{ - printk(KERN_INFO "S5P CEC for TVOUT Driver, exiting\n"); - kfree(cec_rx_struct.buffer); - platform_driver_unregister(&s5p_cec_driver); -} + static void __exit s5p_cec_exit(void) + { + printk(KERN_INFO "S5P CEC for TVOUT Driver, exiting\n"); + kfree(cec_rx_struct.buffer); + platform_driver_unregister(&s5p_cec_driver); + } -module_init(s5p_cec_init); -module_exit(s5p_cec_exit); + module_init(s5p_cec_init); + module_exit(s5p_cec_exit); #endif From 5fd9b96d8f6aa5f6a7b1523e070ae0a1ba6c2ee6 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 15:08:34 +0200 Subject: [PATCH 11/30] not sure where regs-cec.h should go. seem architecture independent, so keep it in the s5p module. --- .../include/mach/regs-cec.h.disabled | 93 +++++++++++++++++++ .../include/mach/regs-cec.h.disabled | 93 +++++++++++++++++++ drivers/media/platform/s5p-tv/cec_drv.c | 6 +- drivers/media/platform/s5p-tv/cec_hw.c | 2 +- 4 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 arch/arm/mach-exynos/include/mach/regs-cec.h.disabled create mode 100644 arch/arm/mach-s5pv210/include/mach/regs-cec.h.disabled diff --git a/arch/arm/mach-exynos/include/mach/regs-cec.h.disabled b/arch/arm/mach-exynos/include/mach/regs-cec.h.disabled new file mode 100644 index 00000000000000..1b5ed095f59f58 --- /dev/null +++ b/arch/arm/mach-exynos/include/mach/regs-cec.h.disabled @@ -0,0 +1,93 @@ +/* linux/arch/arm/mach-exynos/include/mach/regs-cec.h + * + * Copyright (c) 2010 Samsung Electronics + * http://www.samsung.com/ + * + * CEC register header file for Samsung TVOUT driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ARCH_ARM_REGS_CEC_H +#define __ARCH_ARM_REGS_CEC_H + +/* + * Register part + */ +#define S5P_CES_STATUS_0 (0x0000) +#define S5P_CES_STATUS_1 (0x0004) +#define S5P_CES_STATUS_2 (0x0008) +#define S5P_CES_STATUS_3 (0x000C) +#define S5P_CES_IRQ_MASK (0x0010) +#define S5P_CES_IRQ_CLEAR (0x0014) +#define S5P_CES_LOGIC_ADDR (0x0020) +#define S5P_CES_DIVISOR_0 (0x0030) +#define S5P_CES_DIVISOR_1 (0x0034) +#define S5P_CES_DIVISOR_2 (0x0038) +#define S5P_CES_DIVISOR_3 (0x003C) + +#define S5P_CES_TX_CTRL (0x0040) +#define S5P_CES_TX_BYTES (0x0044) +#define S5P_CES_TX_STAT0 (0x0060) +#define S5P_CES_TX_STAT1 (0x0064) +#define S5P_CES_TX_BUFF0 (0x0080) +#define S5P_CES_TX_BUFF1 (0x0084) +#define S5P_CES_TX_BUFF2 (0x0088) +#define S5P_CES_TX_BUFF3 (0x008C) +#define S5P_CES_TX_BUFF4 (0x0090) +#define S5P_CES_TX_BUFF5 (0x0094) +#define S5P_CES_TX_BUFF6 (0x0098) +#define S5P_CES_TX_BUFF7 (0x009C) +#define S5P_CES_TX_BUFF8 (0x00A0) +#define S5P_CES_TX_BUFF9 (0x00A4) +#define S5P_CES_TX_BUFF10 (0x00A8) +#define S5P_CES_TX_BUFF11 (0x00AC) +#define S5P_CES_TX_BUFF12 (0x00B0) +#define S5P_CES_TX_BUFF13 (0x00B4) +#define S5P_CES_TX_BUFF14 (0x00B8) +#define S5P_CES_TX_BUFF15 (0x00BC) + +#define S5P_CES_RX_CTRL (0x00C0) +#define S5P_CES_RX_STAT0 (0x00E0) +#define S5P_CES_RX_STAT1 (0x00E4) +#define S5P_CES_RX_BUFF0 (0x0100) +#define S5P_CES_RX_BUFF1 (0x0104) +#define S5P_CES_RX_BUFF2 (0x0108) +#define S5P_CES_RX_BUFF3 (0x010C) +#define S5P_CES_RX_BUFF4 (0x0110) +#define S5P_CES_RX_BUFF5 (0x0114) +#define S5P_CES_RX_BUFF6 (0x0118) +#define S5P_CES_RX_BUFF7 (0x011C) +#define S5P_CES_RX_BUFF8 (0x0120) +#define S5P_CES_RX_BUFF9 (0x0124) +#define S5P_CES_RX_BUFF10 (0x0128) +#define S5P_CES_RX_BUFF11 (0x012C) +#define S5P_CES_RX_BUFF12 (0x0130) +#define S5P_CES_RX_BUFF13 (0x0134) +#define S5P_CES_RX_BUFF14 (0x0138) +#define S5P_CES_RX_BUFF15 (0x013C) + +#define S5P_CES_RX_FILTER_CTRL (0x0180) +#define S5P_CES_RX_FILTER_TH (0x0184) + +/* + * Bit definition part + */ +#define S5P_CES_IRQ_TX_DONE (1<<0) +#define S5P_CES_IRQ_TX_ERROR (1<<1) +#define S5P_CES_IRQ_RX_DONE (1<<4) +#define S5P_CES_IRQ_RX_ERROR (1<<5) + +#define S5P_CES_TX_CTRL_START (1<<0) +#define S5P_CES_TX_CTRL_BCAST (1<<1) +#define S5P_CES_TX_CTRL_RETRY (0x04<<4) +#define S5P_CES_TX_CTRL_RESET (1<<7) + +#define S5P_CES_RX_CTRL_ENABLE (1<<0) +#define S5P_CES_RX_CTRL_RESET (1<<7) + +#define S5P_CES_LOGIC_ADDR_MASK (0xF) + +#endif /* __ARCH_ARM_REGS_CEC_H */ diff --git a/arch/arm/mach-s5pv210/include/mach/regs-cec.h.disabled b/arch/arm/mach-s5pv210/include/mach/regs-cec.h.disabled new file mode 100644 index 00000000000000..1b5ed095f59f58 --- /dev/null +++ b/arch/arm/mach-s5pv210/include/mach/regs-cec.h.disabled @@ -0,0 +1,93 @@ +/* linux/arch/arm/mach-exynos/include/mach/regs-cec.h + * + * Copyright (c) 2010 Samsung Electronics + * http://www.samsung.com/ + * + * CEC register header file for Samsung TVOUT driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ARCH_ARM_REGS_CEC_H +#define __ARCH_ARM_REGS_CEC_H + +/* + * Register part + */ +#define S5P_CES_STATUS_0 (0x0000) +#define S5P_CES_STATUS_1 (0x0004) +#define S5P_CES_STATUS_2 (0x0008) +#define S5P_CES_STATUS_3 (0x000C) +#define S5P_CES_IRQ_MASK (0x0010) +#define S5P_CES_IRQ_CLEAR (0x0014) +#define S5P_CES_LOGIC_ADDR (0x0020) +#define S5P_CES_DIVISOR_0 (0x0030) +#define S5P_CES_DIVISOR_1 (0x0034) +#define S5P_CES_DIVISOR_2 (0x0038) +#define S5P_CES_DIVISOR_3 (0x003C) + +#define S5P_CES_TX_CTRL (0x0040) +#define S5P_CES_TX_BYTES (0x0044) +#define S5P_CES_TX_STAT0 (0x0060) +#define S5P_CES_TX_STAT1 (0x0064) +#define S5P_CES_TX_BUFF0 (0x0080) +#define S5P_CES_TX_BUFF1 (0x0084) +#define S5P_CES_TX_BUFF2 (0x0088) +#define S5P_CES_TX_BUFF3 (0x008C) +#define S5P_CES_TX_BUFF4 (0x0090) +#define S5P_CES_TX_BUFF5 (0x0094) +#define S5P_CES_TX_BUFF6 (0x0098) +#define S5P_CES_TX_BUFF7 (0x009C) +#define S5P_CES_TX_BUFF8 (0x00A0) +#define S5P_CES_TX_BUFF9 (0x00A4) +#define S5P_CES_TX_BUFF10 (0x00A8) +#define S5P_CES_TX_BUFF11 (0x00AC) +#define S5P_CES_TX_BUFF12 (0x00B0) +#define S5P_CES_TX_BUFF13 (0x00B4) +#define S5P_CES_TX_BUFF14 (0x00B8) +#define S5P_CES_TX_BUFF15 (0x00BC) + +#define S5P_CES_RX_CTRL (0x00C0) +#define S5P_CES_RX_STAT0 (0x00E0) +#define S5P_CES_RX_STAT1 (0x00E4) +#define S5P_CES_RX_BUFF0 (0x0100) +#define S5P_CES_RX_BUFF1 (0x0104) +#define S5P_CES_RX_BUFF2 (0x0108) +#define S5P_CES_RX_BUFF3 (0x010C) +#define S5P_CES_RX_BUFF4 (0x0110) +#define S5P_CES_RX_BUFF5 (0x0114) +#define S5P_CES_RX_BUFF6 (0x0118) +#define S5P_CES_RX_BUFF7 (0x011C) +#define S5P_CES_RX_BUFF8 (0x0120) +#define S5P_CES_RX_BUFF9 (0x0124) +#define S5P_CES_RX_BUFF10 (0x0128) +#define S5P_CES_RX_BUFF11 (0x012C) +#define S5P_CES_RX_BUFF12 (0x0130) +#define S5P_CES_RX_BUFF13 (0x0134) +#define S5P_CES_RX_BUFF14 (0x0138) +#define S5P_CES_RX_BUFF15 (0x013C) + +#define S5P_CES_RX_FILTER_CTRL (0x0180) +#define S5P_CES_RX_FILTER_TH (0x0184) + +/* + * Bit definition part + */ +#define S5P_CES_IRQ_TX_DONE (1<<0) +#define S5P_CES_IRQ_TX_ERROR (1<<1) +#define S5P_CES_IRQ_RX_DONE (1<<4) +#define S5P_CES_IRQ_RX_ERROR (1<<5) + +#define S5P_CES_TX_CTRL_START (1<<0) +#define S5P_CES_TX_CTRL_BCAST (1<<1) +#define S5P_CES_TX_CTRL_RETRY (0x04<<4) +#define S5P_CES_TX_CTRL_RESET (1<<7) + +#define S5P_CES_RX_CTRL_ENABLE (1<<0) +#define S5P_CES_RX_CTRL_RESET (1<<7) + +#define S5P_CES_LOGIC_ADDR_MASK (0xF) + +#endif /* __ARCH_ARM_REGS_CEC_H */ diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index 0bc1d932e1ba50..e0cca1cd697b1e 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -20,16 +20,14 @@ #include #include -//#include "../../../arch/arm/plat-samsung/include/plat/tvout.h" + struct s5p_platform_cec { void (*cfg_gpio)(struct platform_device *pdev); }; - -//#include "s5p_tvout_common_lib.h" -//#include "hw_if/hw_if.h" #include "cec_hw.h" + MODULE_AUTHOR("KyungHwan Kim "); MODULE_DESCRIPTION("Samsung S5P CEC driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/s5p-tv/cec_hw.c b/drivers/media/platform/s5p-tv/cec_hw.c index b414e61a9f1d75..a314824fb28150 100644 --- a/drivers/media/platform/s5p-tv/cec_hw.c +++ b/drivers/media/platform/s5p-tv/cec_hw.c @@ -14,7 +14,7 @@ #include #include -#include +//#include // doesn't seem to work #include "cec_hw.h" #include "regs-cec.h" // somehow mach/regs-cec.h isn't picked up From 99b80bb51c33cd0512c32606a35b0e92f10a46f8 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 16:03:11 +0200 Subject: [PATCH 12/30] Hook up the cec-platform to the per-architecture registration. And it crashed! so it works! --- arch/arm/mach-exynos/mach-hkdk4412.c | 1 + arch/arm/mach-exynos/mach-origen.c | 1 + arch/arm/mach-exynos/mach-smdkv310.c | 1 + arch/arm/plat-samsung/devs.c | 2 +- arch/arm/plat-samsung/include/plat/devs.h | 2 +- arch/arm/plat-samsung/include/plat/tv-core.h | 7 +++++++ drivers/media/platform/s5p-tv/cec_drv.c | 3 +++ 7 files changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-exynos/mach-hkdk4412.c b/arch/arm/mach-exynos/mach-hkdk4412.c index 2e0cf0a52e6d93..f7fb7e8ab164e6 100644 --- a/arch/arm/mach-exynos/mach-hkdk4412.c +++ b/arch/arm/mach-exynos/mach-hkdk4412.c @@ -393,6 +393,7 @@ static struct platform_device *hkdk4412_devices[] __initdata = { &mali_gpu_device, #if defined(CONFIG_S5P_DEV_TV) &s5p_device_hdmi, + &s5p_device_cec, &s5p_device_i2c_hdmiphy, &s5p_device_mixer, &hdmi_fixed_voltage, diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index 5e34b9c16196c4..d283b06db8d8ab 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -705,6 +705,7 @@ static struct platform_device *origen_devices[] __initdata = { &s5p_device_fimd0, &s5p_device_g2d, &s5p_device_hdmi, + &s5p_device_cec, &s5p_device_i2c_hdmiphy, &s5p_device_jpeg, &s5p_device_mfc, diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c index 35548e3c097d8e..00174f821fbc09 100644 --- a/arch/arm/mach-exynos/mach-smdkv310.c +++ b/arch/arm/mach-exynos/mach-smdkv310.c @@ -315,6 +315,7 @@ static struct platform_device *smdkv310_devices[] __initdata = { &smdkv310_smsc911x, &exynos4_device_ahci, &s5p_device_hdmi, + &s5p_device_cec, &s5p_device_mixer, }; diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index ab9a64ab26f634..36ca6043222d09 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c @@ -1362,7 +1362,7 @@ static struct resource s5p_cec_resources[] = { [1] = DEFINE_RES_IRQ(IRQ_CEC), }; -struct platform_device s5p_device_hdmi_cec = { +struct platform_device s5p_device_cec = { .name = "s5p-cec", .id = -1, .num_resources = ARRAY_SIZE(s5p_cec_resources), diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 310e629afa7f8e..98b1a96b520bf2 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -87,7 +87,7 @@ extern struct platform_device mali_gpu_device; extern struct platform_device s5p_device_fimd0; extern struct platform_device s5p_device_hdmi; -extern struct platform_device s5p_device_hdmi_cec; +extern struct platform_device s5p_device_cec; extern struct platform_device s5p_device_i2c_hdmiphy; extern struct platform_device s5p_device_mfc; extern struct platform_device s5p_device_mfc_l; diff --git a/arch/arm/plat-samsung/include/plat/tv-core.h b/arch/arm/plat-samsung/include/plat/tv-core.h index 3bc34f3ce28fb6..cc0b2265bfad09 100644 --- a/arch/arm/plat-samsung/include/plat/tv-core.h +++ b/arch/arm/plat-samsung/include/plat/tv-core.h @@ -27,6 +27,13 @@ static inline void s5p_hdmi_setname(char *name) #endif } +static inline void s5p_cec_setname(char *name) +{ +#ifdef CONFIG_S5P_DEV_TV + s5p_device_cec.name = name; +#endif +} + static inline void s5p_mixer_setname(char *name) { #ifdef CONFIG_S5P_DEV_TV diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index e0cca1cd697b1e..efb3f17458823f 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -268,10 +268,13 @@ static irqreturn_t s5p_cec_irq_handler(int irq, void *dev_id) static int s5p_cec_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct s5p_platform_cec *pdata; u8 *buffer = NULL; int irq_num; int ret = 0; + + dev_info(dev, "probe start\n"); pdata = to_tvout_plat(&pdev->dev); printk(KERN_INFO "s5p_cec_probe: pdata=%p\n", pdata); From 6431be288297ebecfc0b6344f268bd4cbd4ce001 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 16:07:26 +0200 Subject: [PATCH 13/30] Fix one crash --- drivers/media/platform/s5p-tv/cec_drv.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index efb3f17458823f..299b10b81cd8fa 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -277,10 +277,11 @@ static int s5p_cec_probe(struct platform_device *pdev) dev_info(dev, "probe start\n"); pdata = to_tvout_plat(&pdev->dev); - printk(KERN_INFO "s5p_cec_probe: pdata=%p\n", pdata); - - if (pdata->cfg_gpio) + if (pdata && pdata->cfg_gpio) + { + printk(KERN_INFO "s5p_cec_probe: pdata=%p\n", pdata); pdata->cfg_gpio(pdev); + } /* get ioremap addr */ s5p_cec_mem_probe(pdev); From 89a97aa5ec364639fc6a0bc74d470014a3d0848d Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 16:36:22 +0200 Subject: [PATCH 14/30] Give probe() a chance of working. More error reporting/handling --- drivers/media/platform/s5p-tv/cec_drv.c | 74 +++++++++++++++++-------- drivers/media/platform/s5p-tv/cec_hw.c | 15 ++--- drivers/media/platform/s5p-tv/cec_hw.h | 2 +- 3 files changed, 59 insertions(+), 32 deletions(-) diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index 299b10b81cd8fa..215e3991241505 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -19,6 +19,7 @@ #include #include #include +#include struct s5p_platform_cec { @@ -45,15 +46,27 @@ MODULE_LICENSE("GPL"); #define CEC_TX_BUFF_SIZE 16 +#define TV_CLK_GET_WITH_ERR_CHECK(clk, pdev, clk_name) \ + do { \ + clk = clk_get(&pdev->dev, clk_name); \ + if (IS_ERR(clk)) { \ + printk(KERN_ERR \ + "failed to find clock %s\n", clk_name); \ + return -ENOENT; \ + } \ + } while (0); + static atomic_t hdmi_on = ATOMIC_INIT(0); static DEFINE_MUTEX(cec_lock); +struct clk *hdmi_cec_clk; static int s5p_cec_open(struct inode *inode, struct file *file) { int ret = 0; mutex_lock(&cec_lock); + clk_enable(hdmi_cec_clk); if (atomic_read(&hdmi_on)) { tvout_dbg("do not allow multiple open for tvout cec\n"); @@ -80,7 +93,6 @@ static int s5p_cec_open(struct inode *inode, struct file *file) return ret; } - static int s5p_cec_release(struct inode *inode, struct file *file) { atomic_dec(&hdmi_on); @@ -88,29 +100,32 @@ static int s5p_cec_release(struct inode *inode, struct file *file) s5p_cec_mask_tx_interrupts(); s5p_cec_mask_rx_interrupts(); + clk_disable(hdmi_cec_clk); + clk_put(hdmi_cec_clk); + return 0; } static ssize_t s5p_cec_read(struct file *file, char __user *buffer, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { ssize_t retval; + unsigned long spin_flags; - printk("s5p_cec_read, count = %lu", (unsigned long)count); - - if (wait_event_interruptible(cec_rx_struct.waitq, atomic_read(&cec_rx_struct.state) == STATE_DONE)) + if (wait_event_interruptible(cec_rx_struct.waitq, + atomic_read(&cec_rx_struct.state) == STATE_DONE)) { return -ERESTARTSYS; - - spin_lock_irq(&cec_rx_struct.lock); + } + spin_lock_irqsave(&cec_rx_struct.lock, spin_flags); if (cec_rx_struct.size > count) { - spin_unlock_irq(&cec_rx_struct.lock); + spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags); return -1; } if (copy_to_user(buffer, cec_rx_struct.buffer, cec_rx_struct.size)) { - spin_unlock_irq(&cec_rx_struct.lock); + spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags); printk(KERN_ERR " copy_to_user() failed!\n"); return -EFAULT; @@ -119,14 +134,14 @@ static ssize_t s5p_cec_read(struct file *file, char __user *buffer, retval = cec_rx_struct.size; s5p_cec_set_rx_state(STATE_RX); - spin_unlock_irq(&cec_rx_struct.lock); + spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags); return retval; } static ssize_t s5p_cec_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { char *data; @@ -155,8 +170,12 @@ static ssize_t s5p_cec_write(struct file *file, const char __user *buffer, kfree(data); /* wait for interrupt */ - if (wait_event_interruptible(cec_tx_struct.waitq, atomic_read(&cec_tx_struct.state) != STATE_TX)) + if (wait_event_interruptible(cec_tx_struct.waitq, + atomic_read(&cec_tx_struct.state) + != STATE_TX)) { + return -ERESTARTSYS; + } if (atomic_read(&cec_tx_struct.state) == STATE_ERROR) return -1; @@ -284,51 +303,58 @@ static int s5p_cec_probe(struct platform_device *pdev) } /* get ioremap addr */ - s5p_cec_mem_probe(pdev); + ret = s5p_cec_mem_probe(pdev); + if (ret != 0) { + printk(KERN_ERR "failed to s5p_cec_mem_probe ret = %d\n", ret); + goto err_mem_probe; + } if (misc_register(&cec_misc_device)) { printk(KERN_WARNING " Couldn't register device 10, %d.\n", CEC_MINOR); ret = -EBUSY; - goto out; + goto err_misc_register; } irq_num = platform_get_irq(pdev, 0); if (irq_num < 0) { printk(KERN_ERR "failed to get %s irq resource\n", "cec"); ret = -EBUSY; - goto irq_err; + goto err_get_irq; } if (request_irq(irq_num, s5p_cec_irq_handler, IRQF_DISABLED, pdev->name, &pdev->id)) { printk(KERN_ERR "failed to install %s irq (%d)\n", "cec", ret); ret = -EBUSY; - goto irq_err; + goto err_request_irq; } init_waitqueue_head(&cec_rx_struct.waitq); spin_lock_init(&cec_rx_struct.lock); init_waitqueue_head(&cec_tx_struct.waitq); - if (kmalloc(CEC_TX_BUFF_SIZE, GFP_KERNEL)) { + buffer = kmalloc(CEC_TX_BUFF_SIZE, GFP_KERNEL); + if (!buffer) { printk(KERN_ERR " kmalloc() failed!\n"); + misc_deregister(&cec_misc_device); ret = -EIO; - goto kmalloc_err; + goto err_kmalloc; } cec_rx_struct.buffer = buffer; cec_rx_struct.size = 0; + TV_CLK_GET_WITH_ERR_CHECK(hdmi_cec_clk, pdev, "hdmicec"); - return 0; - -kmalloc_err: +err_kmalloc: free_irq(irq_num, NULL); -irq_err: +err_request_irq: +err_get_irq: misc_deregister(&cec_misc_device); -out: +err_misc_register: +err_mem_probe: return ret; - } + static int s5p_cec_remove(struct platform_device *pdev) { int irq_num = platform_get_irq(pdev, 0); diff --git a/drivers/media/platform/s5p-tv/cec_hw.c b/drivers/media/platform/s5p-tv/cec_hw.c index a314824fb28150..5c7d721b3ad27d 100644 --- a/drivers/media/platform/s5p-tv/cec_hw.c +++ b/drivers/media/platform/s5p-tv/cec_hw.c @@ -195,33 +195,34 @@ void s5p_cec_get_rx_buf(u32 size, u8 *buffer) } } -void s5p_cec_mem_probe(struct platform_device *pdev) +int s5p_cec_mem_probe(struct platform_device *pdev) { struct resource *res; size_t size = 0; - int ret; + int ret = 0; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(&pdev->dev, "failed to get memory region resource for cec\n"); - ret = -ENOENT; + return -ENOENT; } else size = resource_size(res); cec_mem = request_mem_region(res->start, size, pdev->name); if (cec_mem == NULL) { - dev_err(&pdev->dev, - "failed to get memory region for cec\n"); - ret = -ENOENT; + dev_err(&pdev->dev, "failed to get memory at %p, size %i, name '%s'\n", + res->start, size, pdev->name); + return -ENOENT; } cec_base = ioremap(res->start, size); if (cec_base == NULL) { dev_err(&pdev->dev, "failed to ioremap address region for cec\n"); - ret = -ENOENT; + return -ENOENT; } + return ret; } int __init s5p_cec_mem_release(struct platform_device *pdev) diff --git a/drivers/media/platform/s5p-tv/cec_hw.h b/drivers/media/platform/s5p-tv/cec_hw.h index 514bf8548f61bf..57c032765cada7 100644 --- a/drivers/media/platform/s5p-tv/cec_hw.h +++ b/drivers/media/platform/s5p-tv/cec_hw.h @@ -62,7 +62,7 @@ u32 s5p_cec_get_status(void); void s5p_clr_pending_tx(void); void s5p_clr_pending_rx(void); void s5p_cec_get_rx_buf(u32 size, u8 *buffer); -void s5p_cec_mem_probe(struct platform_device *pdev); +int s5p_cec_mem_probe(struct platform_device *pdev); #endif \ No newline at end of file From 5d0d3f502e45c549c842bb382566e93d5935fca4 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 16:45:55 +0200 Subject: [PATCH 15/30] Not sure what the clock is good for, disable it for now. --- drivers/media/platform/s5p-tv/cec_drv.c | 28 +++++++++++-------------- drivers/media/platform/s5p-tv/cec_hw.c | 1 + 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index 215e3991241505..2c87c8da1c4cc4 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -46,27 +46,16 @@ MODULE_LICENSE("GPL"); #define CEC_TX_BUFF_SIZE 16 -#define TV_CLK_GET_WITH_ERR_CHECK(clk, pdev, clk_name) \ - do { \ - clk = clk_get(&pdev->dev, clk_name); \ - if (IS_ERR(clk)) { \ - printk(KERN_ERR \ - "failed to find clock %s\n", clk_name); \ - return -ENOENT; \ - } \ - } while (0); - - static atomic_t hdmi_on = ATOMIC_INIT(0); static DEFINE_MUTEX(cec_lock); -struct clk *hdmi_cec_clk; +//struct clk *hdmi_cec_clk; static int s5p_cec_open(struct inode *inode, struct file *file) { int ret = 0; mutex_lock(&cec_lock); - clk_enable(hdmi_cec_clk); + //clk_enable(hdmi_cec_clk); if (atomic_read(&hdmi_on)) { tvout_dbg("do not allow multiple open for tvout cec\n"); @@ -100,8 +89,8 @@ static int s5p_cec_release(struct inode *inode, struct file *file) s5p_cec_mask_tx_interrupts(); s5p_cec_mask_rx_interrupts(); - clk_disable(hdmi_cec_clk); - clk_put(hdmi_cec_clk); + //clk_disable(hdmi_cec_clk); + //clk_put(hdmi_cec_clk); return 0; } @@ -342,7 +331,14 @@ static int s5p_cec_probe(struct platform_device *pdev) cec_rx_struct.buffer = buffer; cec_rx_struct.size = 0; - TV_CLK_GET_WITH_ERR_CHECK(hdmi_cec_clk, pdev, "hdmicec"); + +#if 0 // Someone on the internet does this, most people don't: + clk = clk_get(&pdev->dev, clk_name); + if (IS_ERR(clk)) { + printk(KERN_ERR "failed to find clock %s\n", clk_name); + return -ENOENT; + } +#endif err_kmalloc: free_irq(irq_num, NULL); diff --git a/drivers/media/platform/s5p-tv/cec_hw.c b/drivers/media/platform/s5p-tv/cec_hw.c index 5c7d721b3ad27d..53d137e6884acf 100644 --- a/drivers/media/platform/s5p-tv/cec_hw.c +++ b/drivers/media/platform/s5p-tv/cec_hw.c @@ -227,6 +227,7 @@ int s5p_cec_mem_probe(struct platform_device *pdev) int __init s5p_cec_mem_release(struct platform_device *pdev) { + dev_info(&pdev->dev, "releasing memory\n"); iounmap(cec_base); if (cec_mem != NULL) { if (release_resource(cec_mem)) From 7b8d88b16a39865010644fe750dca8be5ec32bae Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 17:24:34 +0200 Subject: [PATCH 16/30] more tracing fix unloading: release kmalloc-ed() memory --- drivers/media/platform/s5p-tv/cec_drv.c | 69 ++++++++++++++----------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index 2c87c8da1c4cc4..2333795cd72992 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -48,11 +48,12 @@ MODULE_LICENSE("GPL"); static atomic_t hdmi_on = ATOMIC_INIT(0); static DEFINE_MUTEX(cec_lock); -//struct clk *hdmi_cec_clk; +//struct clk *hdmi_cec_clk; // Seems to be an exynos5 thingie. probe() needs work static int s5p_cec_open(struct inode *inode, struct file *file) { int ret = 0; + printk(KERN_INFO "s5p_cec_open\n"); mutex_lock(&cec_lock); //clk_enable(hdmi_cec_clk); @@ -84,6 +85,8 @@ static int s5p_cec_open(struct inode *inode, struct file *file) static int s5p_cec_release(struct inode *inode, struct file *file) { + printk(KERN_INFO "s5p_cec_release\n"); + atomic_dec(&hdmi_on); s5p_cec_mask_tx_interrupts(); @@ -100,6 +103,8 @@ static ssize_t s5p_cec_read(struct file *file, char __user *buffer, { ssize_t retval; unsigned long spin_flags; + + printk(KERN_INFO "s5p_cec_read, %li bytes\n", (long)count); if (wait_event_interruptible(cec_rx_struct.waitq, atomic_read(&cec_rx_struct.state) == STATE_DONE)) { @@ -177,7 +182,7 @@ static long s5p_cec_ioctl(struct file *file, unsigned int cmd, { u32 laddr; - printk("s5p_cec_read, cmd = %u, arg = %lu", cmd, arg); + printk(KERN_INFO "s5p_cec_ioctl, cmd = %u, arg = %lu\n", cmd, arg); switch (cmd) { case CEC_IOC_SETLADDR: @@ -198,6 +203,7 @@ static long s5p_cec_ioctl(struct file *file, unsigned int cmd, static u32 s5p_cec_poll(struct file *file, poll_table *wait) { + printk(KERN_INFO "s5p_cec_poll\n"); poll_wait(file, &cec_rx_struct.waitq, wait); if (atomic_read(&cec_rx_struct.state) == STATE_DONE) @@ -281,6 +287,7 @@ static int s5p_cec_probe(struct platform_device *pdev) u8 *buffer = NULL; int irq_num; int ret = 0; + struct resource *res; dev_info(dev, "probe start\n"); @@ -304,16 +311,18 @@ static int s5p_cec_probe(struct platform_device *pdev) goto err_misc_register; } - irq_num = platform_get_irq(pdev, 0); - if (irq_num < 0) { - printk(KERN_ERR "failed to get %s irq resource\n", "cec"); - ret = -EBUSY; + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res == NULL) { + dev_err(&pdev->dev, "Failed to get irq resource.\n"); + ret = -ENOENT; goto err_get_irq; } + irq_num = res->start; - if (request_irq(irq_num, s5p_cec_irq_handler, IRQF_DISABLED, pdev->name, &pdev->id)) { - printk(KERN_ERR "failed to install %s irq (%d)\n", "cec", ret); - ret = -EBUSY; + dev_info(dev, "Requesting irq %i for %s\n", irq_num, pdev->name); + ret = request_irq(irq_num, s5p_cec_irq_handler, IRQF_DISABLED, pdev->name, &pdev->id); + if (ret != 0) { + dev_err(dev, "Failed to install irq (%d), error %i\n", irq_num, ret); goto err_request_irq; } @@ -324,7 +333,6 @@ static int s5p_cec_probe(struct platform_device *pdev) buffer = kmalloc(CEC_TX_BUFF_SIZE, GFP_KERNEL); if (!buffer) { printk(KERN_ERR " kmalloc() failed!\n"); - misc_deregister(&cec_misc_device); ret = -EIO; goto err_kmalloc; } @@ -336,10 +344,15 @@ static int s5p_cec_probe(struct platform_device *pdev) clk = clk_get(&pdev->dev, clk_name); if (IS_ERR(clk)) { printk(KERN_ERR "failed to find clock %s\n", clk_name); - return -ENOENT; + //return -ENOENT; + goto err_clock; } #endif + dev_info(&pdev->dev, "probe successful\n"); + return ret; // All good + + // unwind the allocations on error err_kmalloc: free_irq(irq_num, NULL); err_request_irq: @@ -350,15 +363,24 @@ static int s5p_cec_probe(struct platform_device *pdev) return ret; } - static int s5p_cec_remove(struct platform_device *pdev) { - int irq_num = platform_get_irq(pdev, 0); - printk(KERN_INFO "s5p_cec_remove, irq=%i\n", irq_num); - - free_irq(irq_num, NULL); + struct device *dev = &pdev->dev; + struct resource *res; + + dev_info(dev, "s5p_cec_remove, cec_rx_struct.buffer=%p\n", cec_rx_struct.buffer); + if(cec_rx_struct.buffer) + kfree(cec_rx_struct.buffer); + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if(res) + { + int irq_num = res->start; + printk(KERN_INFO "s5p_cec_remove, irq=%i\n", irq_num); + free_irq(irq_num, NULL); + } + misc_deregister(&cec_misc_device); - return 0; } @@ -380,22 +402,9 @@ static int s5p_cec_resume(struct platform_device *dev) #define s5p_cec_resume NULL #endif -#if 0 -static struct platform_device_id hdmi_driver_types[] = { - { - .name = "s5pv210-hdmi", - }, { - .name = "exynos4-hdmi", - }, { - /* end node */ - } -}; -#endif - static struct platform_driver s5p_cec_driver = { .probe = s5p_cec_probe, .remove = s5p_cec_remove, - //.id_table = hdmi_driver_types, // Shouldn't be necessary .suspend = s5p_cec_suspend, .resume = s5p_cec_resume, .driver = { From 197a6811702138809ab24aa687294ff0750cfcd8 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 18:48:22 +0200 Subject: [PATCH 17/30] status update --- README | 11 ++++++----- drivers/media/platform/s5p-tv/Kconfig | 2 +- drivers/media/platform/s5p-tv/cec_drv.c | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README b/README index bb9fabdf078da7..1a8f273f0a6d6e 100644 --- a/README +++ b/README @@ -1,16 +1,17 @@ Summary: Trying to get CEC (tv-remote control over HDMI) working on linux. There appear to be android-kernel sources. - The hardkernel linux doesn't have them + The hardkernel linux-tree doesn't have those Status: Copied s5p-cec code from all over the internet Made it compile as module (s5p-cec.ko) - It can be insmod-ed succesfully, that's all - + It can be insmod, it allocates memory and irq, /dev/CEC is registered. + rmmod will mess up your system, requiring a reboot + TODO: - Make it do something - Look at the latest android kernel sources + Try to read/write some data to /dev/CEC + Merge latest android sources into here http://dn.odroid.com/Android_Alpha_4.0.3/BSP/ Cleanup this tree, so it becomes a nice diff upon hardkernel's 3.8 tree diff --git a/drivers/media/platform/s5p-tv/Kconfig b/drivers/media/platform/s5p-tv/Kconfig index 9d67f04f8bd15c..a819eaf0d2ddac 100644 --- a/drivers/media/platform/s5p-tv/Kconfig +++ b/drivers/media/platform/s5p-tv/Kconfig @@ -39,7 +39,7 @@ config VIDEO_SAMSUNG_S5P_HDMI_DEBUG config VIDEO_SAMSUNG_S5P_HDMI_CEC tristate "Enable CEC support for HDMI Driver" depends on VIDEO_SAMSUNG_S5P_HDMI - default y + default n help Enables CEC over the HDMI driver. CEC enables tv-control, and reception of tv-remote diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index 2333795cd72992..d36bbcd413880c 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -301,7 +301,7 @@ static int s5p_cec_probe(struct platform_device *pdev) /* get ioremap addr */ ret = s5p_cec_mem_probe(pdev); if (ret != 0) { - printk(KERN_ERR "failed to s5p_cec_mem_probe ret = %d\n", ret); + printk(KERN_ERR "failed to s5p_cec_mem_probe(). ret = %d\n", ret); goto err_mem_probe; } From e950e9a942be50316cc340d254eebf59cfd84a67 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 20:03:18 +0200 Subject: [PATCH 18/30] found a clock in the android sources, let's use it --- arch/arm/mach-exynos/clock-exynos4.c | 4 +++ drivers/media/platform/s5p-tv/cec_drv.c | 39 +++++++++++++++---------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c index 56b9c93617d255..7de33c3ee67f5b 100644 --- a/arch/arm/mach-exynos/clock-exynos4.c +++ b/arch/arm/mach-exynos/clock-exynos4.c @@ -716,6 +716,10 @@ static struct clk exynos4_init_clocks_off[] = { .parent = &exynos4_clk_aclk_100.clk, .enable = exynos4_clk_ip_perir_ctrl, .ctrlbit = (1 << 14), + }, { + .name = "hdmicec", + .enable = exynos4_clk_ip_perir_ctrl, + .ctrlbit = (1 << 11), }, { .name = "usbhost", .enable = exynos4_clk_ip_fsys_ctrl , diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index d36bbcd413880c..597d866ed14b77 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -48,7 +48,7 @@ MODULE_LICENSE("GPL"); static atomic_t hdmi_on = ATOMIC_INIT(0); static DEFINE_MUTEX(cec_lock); -//struct clk *hdmi_cec_clk; // Seems to be an exynos5 thingie. probe() needs work +struct clk *hdmi_cec_clk; static int s5p_cec_open(struct inode *inode, struct file *file) { @@ -56,7 +56,7 @@ static int s5p_cec_open(struct inode *inode, struct file *file) printk(KERN_INFO "s5p_cec_open\n"); mutex_lock(&cec_lock); - //clk_enable(hdmi_cec_clk); + clk_enable(hdmi_cec_clk); if (atomic_read(&hdmi_on)) { tvout_dbg("do not allow multiple open for tvout cec\n"); @@ -85,14 +85,15 @@ static int s5p_cec_open(struct inode *inode, struct file *file) static int s5p_cec_release(struct inode *inode, struct file *file) { - printk(KERN_INFO "s5p_cec_release\n"); + printk(KERN_INFO "s5p_cec_release, hdmi_on=%i\n", atomic_read(&hdmi_on)); atomic_dec(&hdmi_on); s5p_cec_mask_tx_interrupts(); s5p_cec_mask_rx_interrupts(); - //clk_disable(hdmi_cec_clk); + clk_disable(hdmi_cec_clk); + // clk_get() is done in probe(), so clk_put() is done in remove(), not in release(): //clk_put(hdmi_cec_clk); return 0; @@ -138,6 +139,8 @@ static ssize_t s5p_cec_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { char *data; + + printk(KERN_INFO "s5p_cec_write, %li bytes\n", (long)count); /* check data size */ @@ -148,14 +151,12 @@ static ssize_t s5p_cec_write(struct file *file, const char __user *buffer, if (!data) { printk(KERN_ERR " kmalloc() failed!\n"); - return -1; } if (copy_from_user(data, buffer, count)) { printk(KERN_ERR " copy_from_user() failed!\n"); kfree(data); - return -EFAULT; } @@ -231,6 +232,7 @@ static struct miscdevice cec_misc_device = { static irqreturn_t s5p_cec_irq_handler(int irq, void *dev_id) { u32 status = s5p_cec_get_status(); + printk(KERN_INFO "s5p_cec_irq_handler on irq %i\n", irq); if (status & CEC_STATUS_TX_DONE) { if (status & CEC_STATUS_TX_ERROR) { @@ -340,19 +342,20 @@ static int s5p_cec_probe(struct platform_device *pdev) cec_rx_struct.buffer = buffer; cec_rx_struct.size = 0; -#if 0 // Someone on the internet does this, most people don't: - clk = clk_get(&pdev->dev, clk_name); - if (IS_ERR(clk)) { - printk(KERN_ERR "failed to find clock %s\n", clk_name); - //return -ENOENT; + hdmi_cec_clk = clk_get(&pdev->dev, "hdmicec"); + if (IS_ERR(hdmi_cec_clk)) { + printk(KERN_ERR "failed to find clock 'hdmicec'\n"); + ret = -ENOENT; goto err_clock; } -#endif dev_info(&pdev->dev, "probe successful\n"); return ret; // All good - // unwind the allocations on error + // Unwind the allocations on error +err_clock: + kfree(cec_rx_struct.buffer); + cec_rx_struct.buffer = NULL; err_kmalloc: free_irq(irq_num, NULL); err_request_irq: @@ -367,10 +370,16 @@ static int s5p_cec_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; + dev_info(dev, "s5p_cec_remove, putting clk to sleep\n"); + clk_put(hdmi_cec_clk); + dev_info(dev, "s5p_cec_remove, cec_rx_struct.buffer=%p\n", cec_rx_struct.buffer); if(cec_rx_struct.buffer) + { kfree(cec_rx_struct.buffer); + cec_rx_struct.buffer = NULL; + } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if(res) @@ -414,7 +423,7 @@ static struct platform_driver s5p_cec_driver = { }; #if 0 - // The rest of the modules in s5p-tv do this: + // The rest of the modules in s5p-tv do module_platform_driver() // It makes debugging the probe a bit trickier, so don't do this now module_platform_driver(s5p_cec_driver); #else @@ -428,7 +437,7 @@ static struct platform_driver s5p_cec_driver = { static void __exit s5p_cec_exit(void) { printk(KERN_INFO "S5P CEC for TVOUT Driver, exiting\n"); - kfree(cec_rx_struct.buffer); + //kfree(cec_rx_struct.buffer); // moved to s5p_cec_remove() platform_driver_unregister(&s5p_cec_driver); } From 2e688b32daea212a1bb35e0fb7e282c18fbd8516 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 20:26:14 +0200 Subject: [PATCH 19/30] small fixes --- drivers/gpu/drm/drm_vm.c | 1 + drivers/media/platform/s5p-tv/cec_drv.c | 2 +- drivers/media/platform/s5p-tv/cec_hw.c | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index db7bd292410bad..1d4f7c9fe66189 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -422,6 +422,7 @@ void drm_vm_open_locked(struct drm_device *dev, list_add(&vma_entry->head, &dev->vmalist); } } +EXPORT_SYMBOL_GPL(drm_vm_open_locked); static void drm_vm_open(struct vm_area_struct *vma) { diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index 597d866ed14b77..c2ab70b7ba133e 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -316,7 +316,7 @@ static int s5p_cec_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) { dev_err(&pdev->dev, "Failed to get irq resource.\n"); - ret = -ENOENT; + ret = -ENODEV; goto err_get_irq; } irq_num = res->start; diff --git a/drivers/media/platform/s5p-tv/cec_hw.c b/drivers/media/platform/s5p-tv/cec_hw.c index 53d137e6884acf..c9d93a2e22af79 100644 --- a/drivers/media/platform/s5p-tv/cec_hw.c +++ b/drivers/media/platform/s5p-tv/cec_hw.c @@ -211,8 +211,7 @@ int s5p_cec_mem_probe(struct platform_device *pdev) cec_mem = request_mem_region(res->start, size, pdev->name); if (cec_mem == NULL) { - dev_err(&pdev->dev, "failed to get memory at %p, size %i, name '%s'\n", - res->start, size, pdev->name); + dev_err(&pdev->dev, "failed to get memory at size %i, name %s\n", size, pdev->name); return -ENOENT; } From a5cdef9635cfd0cb5c6f6902f93c40e7d353816a Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 20:59:44 +0200 Subject: [PATCH 20/30] properly free the irq --- drivers/media/platform/s5p-tv/cec_drv.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index c2ab70b7ba133e..d01546cd70200f 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -293,7 +293,8 @@ static int s5p_cec_probe(struct platform_device *pdev) dev_info(dev, "probe start\n"); - pdata = to_tvout_plat(&pdev->dev); + //pdata = to_tvout_plat(&pdev->dev); + pdata = to_platform_device(&pdev->dev)->dev.platform_data; if (pdata && pdata->cfg_gpio) { printk(KERN_INFO "s5p_cec_probe: pdata=%p\n", pdata); @@ -386,7 +387,7 @@ static int s5p_cec_remove(struct platform_device *pdev) { int irq_num = res->start; printk(KERN_INFO "s5p_cec_remove, irq=%i\n", irq_num); - free_irq(irq_num, NULL); + free_irq(irq_num, &pdev->id); } misc_deregister(&cec_misc_device); From 8ed55e56494a7b897bb3e1d4e63e73be262f49c8 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 21:08:28 +0200 Subject: [PATCH 21/30] fix cleanup of mmio and irq's --- drivers/media/platform/s5p-tv/cec_drv.c | 9 ++++++--- drivers/media/platform/s5p-tv/cec_hw.c | 4 ++-- drivers/media/platform/s5p-tv/cec_hw.h | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index d01546cd70200f..e39bd017b31e3a 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -358,11 +358,12 @@ static int s5p_cec_probe(struct platform_device *pdev) kfree(cec_rx_struct.buffer); cec_rx_struct.buffer = NULL; err_kmalloc: - free_irq(irq_num, NULL); + free_irq(irq_num, &pdev->id); err_request_irq: err_get_irq: misc_deregister(&cec_misc_device); err_misc_register: + s5p_cec_mem_release(pdev); err_mem_probe: return ret; } @@ -372,8 +373,7 @@ static int s5p_cec_remove(struct platform_device *pdev) struct device *dev = &pdev->dev; struct resource *res; dev_info(dev, "s5p_cec_remove, putting clk to sleep\n"); - clk_put(hdmi_cec_clk); - + clk_put(hdmi_cec_clk); dev_info(dev, "s5p_cec_remove, cec_rx_struct.buffer=%p\n", cec_rx_struct.buffer); if(cec_rx_struct.buffer) @@ -391,6 +391,9 @@ static int s5p_cec_remove(struct platform_device *pdev) } misc_deregister(&cec_misc_device); + + s5p_cec_mem_release(pdev); + return 0; } diff --git a/drivers/media/platform/s5p-tv/cec_hw.c b/drivers/media/platform/s5p-tv/cec_hw.c index c9d93a2e22af79..ccb35d5e8dd693 100644 --- a/drivers/media/platform/s5p-tv/cec_hw.c +++ b/drivers/media/platform/s5p-tv/cec_hw.c @@ -224,13 +224,13 @@ int s5p_cec_mem_probe(struct platform_device *pdev) return ret; } -int __init s5p_cec_mem_release(struct platform_device *pdev) +int s5p_cec_mem_release(struct platform_device *pdev) { dev_info(&pdev->dev, "releasing memory\n"); iounmap(cec_base); if (cec_mem != NULL) { if (release_resource(cec_mem)) - dev_err(&pdev->dev, "can't remove tvout drv !!\n"); + dev_err(&pdev->dev, "can't remove s5p-cec driver !!\n"); kfree(cec_mem); diff --git a/drivers/media/platform/s5p-tv/cec_hw.h b/drivers/media/platform/s5p-tv/cec_hw.h index 57c032765cada7..3a0e4c13f6e193 100644 --- a/drivers/media/platform/s5p-tv/cec_hw.h +++ b/drivers/media/platform/s5p-tv/cec_hw.h @@ -63,6 +63,6 @@ void s5p_clr_pending_tx(void); void s5p_clr_pending_rx(void); void s5p_cec_get_rx_buf(u32 size, u8 *buffer); int s5p_cec_mem_probe(struct platform_device *pdev); - +int s5p_cec_mem_release(struct platform_device *pdev); #endif \ No newline at end of file From e768be34979756a473152b6fc4dc4762ba6827bf Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 21:18:27 +0200 Subject: [PATCH 22/30] cleanup the diff w.r.t hardkernel's 3.8.y kernel --- arch/arm/mach-exynos/include/mach/map.h | 2 +- .../include/mach/regs-cec.h.disabled | 93 ------------------- arch/arm/mach-s5pv210/include/mach/map.h | 4 +- .../include/mach/regs-cec.h.disabled | 93 ------------------- 4 files changed, 3 insertions(+), 189 deletions(-) delete mode 100644 arch/arm/mach-exynos/include/mach/regs-cec.h.disabled delete mode 100644 arch/arm/mach-s5pv210/include/mach/regs-cec.h.disabled diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 2a222ff9d37c82..49cacd2ef52ca8 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -79,7 +79,7 @@ #define EXYNOS4_PA_KEYPAD 0x100A0000 -#define EXYNOS4_PA_CEC 0x100B0000 +#define EXYNOS4_PA_CEC 0x100B0000 #define EXYNOS4_PA_DMC0 0x10400000 #define EXYNOS4_PA_DMC1 0x10410000 diff --git a/arch/arm/mach-exynos/include/mach/regs-cec.h.disabled b/arch/arm/mach-exynos/include/mach/regs-cec.h.disabled deleted file mode 100644 index 1b5ed095f59f58..00000000000000 --- a/arch/arm/mach-exynos/include/mach/regs-cec.h.disabled +++ /dev/null @@ -1,93 +0,0 @@ -/* linux/arch/arm/mach-exynos/include/mach/regs-cec.h - * - * Copyright (c) 2010 Samsung Electronics - * http://www.samsung.com/ - * - * CEC register header file for Samsung TVOUT driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __ARCH_ARM_REGS_CEC_H -#define __ARCH_ARM_REGS_CEC_H - -/* - * Register part - */ -#define S5P_CES_STATUS_0 (0x0000) -#define S5P_CES_STATUS_1 (0x0004) -#define S5P_CES_STATUS_2 (0x0008) -#define S5P_CES_STATUS_3 (0x000C) -#define S5P_CES_IRQ_MASK (0x0010) -#define S5P_CES_IRQ_CLEAR (0x0014) -#define S5P_CES_LOGIC_ADDR (0x0020) -#define S5P_CES_DIVISOR_0 (0x0030) -#define S5P_CES_DIVISOR_1 (0x0034) -#define S5P_CES_DIVISOR_2 (0x0038) -#define S5P_CES_DIVISOR_3 (0x003C) - -#define S5P_CES_TX_CTRL (0x0040) -#define S5P_CES_TX_BYTES (0x0044) -#define S5P_CES_TX_STAT0 (0x0060) -#define S5P_CES_TX_STAT1 (0x0064) -#define S5P_CES_TX_BUFF0 (0x0080) -#define S5P_CES_TX_BUFF1 (0x0084) -#define S5P_CES_TX_BUFF2 (0x0088) -#define S5P_CES_TX_BUFF3 (0x008C) -#define S5P_CES_TX_BUFF4 (0x0090) -#define S5P_CES_TX_BUFF5 (0x0094) -#define S5P_CES_TX_BUFF6 (0x0098) -#define S5P_CES_TX_BUFF7 (0x009C) -#define S5P_CES_TX_BUFF8 (0x00A0) -#define S5P_CES_TX_BUFF9 (0x00A4) -#define S5P_CES_TX_BUFF10 (0x00A8) -#define S5P_CES_TX_BUFF11 (0x00AC) -#define S5P_CES_TX_BUFF12 (0x00B0) -#define S5P_CES_TX_BUFF13 (0x00B4) -#define S5P_CES_TX_BUFF14 (0x00B8) -#define S5P_CES_TX_BUFF15 (0x00BC) - -#define S5P_CES_RX_CTRL (0x00C0) -#define S5P_CES_RX_STAT0 (0x00E0) -#define S5P_CES_RX_STAT1 (0x00E4) -#define S5P_CES_RX_BUFF0 (0x0100) -#define S5P_CES_RX_BUFF1 (0x0104) -#define S5P_CES_RX_BUFF2 (0x0108) -#define S5P_CES_RX_BUFF3 (0x010C) -#define S5P_CES_RX_BUFF4 (0x0110) -#define S5P_CES_RX_BUFF5 (0x0114) -#define S5P_CES_RX_BUFF6 (0x0118) -#define S5P_CES_RX_BUFF7 (0x011C) -#define S5P_CES_RX_BUFF8 (0x0120) -#define S5P_CES_RX_BUFF9 (0x0124) -#define S5P_CES_RX_BUFF10 (0x0128) -#define S5P_CES_RX_BUFF11 (0x012C) -#define S5P_CES_RX_BUFF12 (0x0130) -#define S5P_CES_RX_BUFF13 (0x0134) -#define S5P_CES_RX_BUFF14 (0x0138) -#define S5P_CES_RX_BUFF15 (0x013C) - -#define S5P_CES_RX_FILTER_CTRL (0x0180) -#define S5P_CES_RX_FILTER_TH (0x0184) - -/* - * Bit definition part - */ -#define S5P_CES_IRQ_TX_DONE (1<<0) -#define S5P_CES_IRQ_TX_ERROR (1<<1) -#define S5P_CES_IRQ_RX_DONE (1<<4) -#define S5P_CES_IRQ_RX_ERROR (1<<5) - -#define S5P_CES_TX_CTRL_START (1<<0) -#define S5P_CES_TX_CTRL_BCAST (1<<1) -#define S5P_CES_TX_CTRL_RETRY (0x04<<4) -#define S5P_CES_TX_CTRL_RESET (1<<7) - -#define S5P_CES_RX_CTRL_ENABLE (1<<0) -#define S5P_CES_RX_CTRL_RESET (1<<7) - -#define S5P_CES_LOGIC_ADDR_MASK (0xF) - -#endif /* __ARCH_ARM_REGS_CEC_H */ diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h index 1533b4871d81b0..de994e08989e07 100644 --- a/arch/arm/mach-s5pv210/include/mach/map.h +++ b/arch/arm/mach-s5pv210/include/mach/map.h @@ -49,8 +49,8 @@ #define S5PV210_PA_PCM2 0xE2B00000 #define S5PV210_PA_CEC 0xE1B00000 -#define S5P_PA_CEC S5PV210_PA_CEC -#define S5P_SZ_CEC SZ_4K +#define S5P_PA_CEC S5PV210_PA_CEC +#define S5P_SZ_CEC SZ_4K #define S5PV210_PA_TIMER 0xE2500000 #define S5PV210_PA_SYSTIMER 0xE2600000 diff --git a/arch/arm/mach-s5pv210/include/mach/regs-cec.h.disabled b/arch/arm/mach-s5pv210/include/mach/regs-cec.h.disabled deleted file mode 100644 index 1b5ed095f59f58..00000000000000 --- a/arch/arm/mach-s5pv210/include/mach/regs-cec.h.disabled +++ /dev/null @@ -1,93 +0,0 @@ -/* linux/arch/arm/mach-exynos/include/mach/regs-cec.h - * - * Copyright (c) 2010 Samsung Electronics - * http://www.samsung.com/ - * - * CEC register header file for Samsung TVOUT driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __ARCH_ARM_REGS_CEC_H -#define __ARCH_ARM_REGS_CEC_H - -/* - * Register part - */ -#define S5P_CES_STATUS_0 (0x0000) -#define S5P_CES_STATUS_1 (0x0004) -#define S5P_CES_STATUS_2 (0x0008) -#define S5P_CES_STATUS_3 (0x000C) -#define S5P_CES_IRQ_MASK (0x0010) -#define S5P_CES_IRQ_CLEAR (0x0014) -#define S5P_CES_LOGIC_ADDR (0x0020) -#define S5P_CES_DIVISOR_0 (0x0030) -#define S5P_CES_DIVISOR_1 (0x0034) -#define S5P_CES_DIVISOR_2 (0x0038) -#define S5P_CES_DIVISOR_3 (0x003C) - -#define S5P_CES_TX_CTRL (0x0040) -#define S5P_CES_TX_BYTES (0x0044) -#define S5P_CES_TX_STAT0 (0x0060) -#define S5P_CES_TX_STAT1 (0x0064) -#define S5P_CES_TX_BUFF0 (0x0080) -#define S5P_CES_TX_BUFF1 (0x0084) -#define S5P_CES_TX_BUFF2 (0x0088) -#define S5P_CES_TX_BUFF3 (0x008C) -#define S5P_CES_TX_BUFF4 (0x0090) -#define S5P_CES_TX_BUFF5 (0x0094) -#define S5P_CES_TX_BUFF6 (0x0098) -#define S5P_CES_TX_BUFF7 (0x009C) -#define S5P_CES_TX_BUFF8 (0x00A0) -#define S5P_CES_TX_BUFF9 (0x00A4) -#define S5P_CES_TX_BUFF10 (0x00A8) -#define S5P_CES_TX_BUFF11 (0x00AC) -#define S5P_CES_TX_BUFF12 (0x00B0) -#define S5P_CES_TX_BUFF13 (0x00B4) -#define S5P_CES_TX_BUFF14 (0x00B8) -#define S5P_CES_TX_BUFF15 (0x00BC) - -#define S5P_CES_RX_CTRL (0x00C0) -#define S5P_CES_RX_STAT0 (0x00E0) -#define S5P_CES_RX_STAT1 (0x00E4) -#define S5P_CES_RX_BUFF0 (0x0100) -#define S5P_CES_RX_BUFF1 (0x0104) -#define S5P_CES_RX_BUFF2 (0x0108) -#define S5P_CES_RX_BUFF3 (0x010C) -#define S5P_CES_RX_BUFF4 (0x0110) -#define S5P_CES_RX_BUFF5 (0x0114) -#define S5P_CES_RX_BUFF6 (0x0118) -#define S5P_CES_RX_BUFF7 (0x011C) -#define S5P_CES_RX_BUFF8 (0x0120) -#define S5P_CES_RX_BUFF9 (0x0124) -#define S5P_CES_RX_BUFF10 (0x0128) -#define S5P_CES_RX_BUFF11 (0x012C) -#define S5P_CES_RX_BUFF12 (0x0130) -#define S5P_CES_RX_BUFF13 (0x0134) -#define S5P_CES_RX_BUFF14 (0x0138) -#define S5P_CES_RX_BUFF15 (0x013C) - -#define S5P_CES_RX_FILTER_CTRL (0x0180) -#define S5P_CES_RX_FILTER_TH (0x0184) - -/* - * Bit definition part - */ -#define S5P_CES_IRQ_TX_DONE (1<<0) -#define S5P_CES_IRQ_TX_ERROR (1<<1) -#define S5P_CES_IRQ_RX_DONE (1<<4) -#define S5P_CES_IRQ_RX_ERROR (1<<5) - -#define S5P_CES_TX_CTRL_START (1<<0) -#define S5P_CES_TX_CTRL_BCAST (1<<1) -#define S5P_CES_TX_CTRL_RETRY (0x04<<4) -#define S5P_CES_TX_CTRL_RESET (1<<7) - -#define S5P_CES_RX_CTRL_ENABLE (1<<0) -#define S5P_CES_RX_CTRL_RESET (1<<7) - -#define S5P_CES_LOGIC_ADDR_MASK (0xF) - -#endif /* __ARCH_ARM_REGS_CEC_H */ From 69c6fbd0abca106fa5534d3300972ef2897b89e0 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 21:25:57 +0200 Subject: [PATCH 23/30] update status --- README | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README b/README index 1a8f273f0a6d6e..35da98f06d9e46 100644 --- a/README +++ b/README @@ -4,15 +4,17 @@ Summary: The hardkernel linux-tree doesn't have those Status: - Copied s5p-cec code from all over the internet + Copied s5p-cec code from all over the internet, mostly from + http://dn.odroid.com/Android_Alpha_4.0.3/BSP/ Made it compile as module (s5p-cec.ko) - It can be insmod, it allocates memory and irq, /dev/CEC is registered. - rmmod will mess up your system, requiring a reboot + Fixed the insmod()/rmmod() stuff. Error handling and resource + free-ing were quite broken. + + cec-client recognizes the device, have not seen data yet: + https://github.com/vamanea/libcec.git TODO: Try to read/write some data to /dev/CEC - Merge latest android sources into here - http://dn.odroid.com/Android_Alpha_4.0.3/BSP/ Cleanup this tree, so it becomes a nice diff upon hardkernel's 3.8 tree From 4aa36de9327d97fddb5738d1e6299693b627865e Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 21:56:10 +0200 Subject: [PATCH 24/30] modify debug output --- drivers/media/platform/s5p-tv/cec_drv.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index e39bd017b31e3a..d038f15ac659ca 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -183,7 +183,7 @@ static long s5p_cec_ioctl(struct file *file, unsigned int cmd, { u32 laddr; - printk(KERN_INFO "s5p_cec_ioctl, cmd = %u, arg = %lu\n", cmd, arg); + printk(KERN_INFO "s5p_cec_ioctl, cmd = 0x%x, arg = 0x%lx\n", cmd, arg); switch (cmd) { case CEC_IOC_SETLADDR: @@ -204,12 +204,13 @@ static long s5p_cec_ioctl(struct file *file, unsigned int cmd, static u32 s5p_cec_poll(struct file *file, poll_table *wait) { - printk(KERN_INFO "s5p_cec_poll\n"); poll_wait(file, &cec_rx_struct.waitq, wait); if (atomic_read(&cec_rx_struct.state) == STATE_DONE) + { + printk(KERN_INFO "s5p_cec_poll: rx = done\n"); return POLLIN | POLLRDNORM; - + } return 0; } From 78e5f6ada609a8f0d87c98fdc1c2492e5a476de3 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 23:20:47 +0200 Subject: [PATCH 25/30] add some debug prints --- drivers/media/platform/s5p-tv/cec_drv.c | 18 ++++++++++++------ drivers/media/platform/s5p-tv/cec_hw.c | 3 +++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index d038f15ac659ca..530feb681e9347 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -160,21 +160,29 @@ static ssize_t s5p_cec_write(struct file *file, const char __user *buffer, return -EFAULT; } + printk(KERN_INFO "\tCopying data\n"); s5p_cec_copy_packet(data, count); kfree(data); + + printk(KERN_INFO "s5p_cec_write: waiting for interrupt\n"); /* wait for interrupt */ if (wait_event_interruptible(cec_tx_struct.waitq, atomic_read(&cec_tx_struct.state) - != STATE_TX)) { - + != STATE_TX)) + { + printk(KERN_INFO "\ttx no interrupt received\n"); return -ERESTARTSYS; } if (atomic_read(&cec_tx_struct.state) == STATE_ERROR) + { + printk(KERN_INFO "\ttx error\n"); return -1; + } + printk(KERN_INFO "\twritten count: %i\n", count); return count; } @@ -296,12 +304,10 @@ static int s5p_cec_probe(struct platform_device *pdev) //pdata = to_tvout_plat(&pdev->dev); pdata = to_platform_device(&pdev->dev)->dev.platform_data; + printk(KERN_INFO "s5p_cec_probe: pdata=%p\n", pdata); if (pdata && pdata->cfg_gpio) - { - printk(KERN_INFO "s5p_cec_probe: pdata=%p\n", pdata); pdata->cfg_gpio(pdev); - } - + /* get ioremap addr */ ret = s5p_cec_mem_probe(pdev); if (ret != 0) { diff --git a/drivers/media/platform/s5p-tv/cec_hw.c b/drivers/media/platform/s5p-tv/cec_hw.c index ccb35d5e8dd693..e6b3cae316ab56 100644 --- a/drivers/media/platform/s5p-tv/cec_hw.c +++ b/drivers/media/platform/s5p-tv/cec_hw.c @@ -141,6 +141,7 @@ void s5p_cec_copy_packet(char *data, size_t count) writeb(data[i], cec_base + (S5P_CEC_TX_BUFF0 + (i * 4))); i++; } + printk(KERN_INFO "s5p_cec_copy_packet(): written %i bytes to cec_base\n", count); writeb(count, cec_base + S5P_CEC_TX_BYTES); s5p_cec_set_tx_state(STATE_TX); @@ -152,6 +153,7 @@ void s5p_cec_copy_packet(char *data, size_t count) else reg &= ~S5P_CEC_TX_CTRL_BCAST; + printk(KERN_INFO "s5p_cec_copy_packet(): flagging S5P_CEC_TX_CTRL\n"); reg |= 0x50; writeb(reg, cec_base + S5P_CEC_TX_CTRL); } @@ -221,6 +223,7 @@ int s5p_cec_mem_probe(struct platform_device *pdev) "failed to ioremap address region for cec\n"); return -ENOENT; } + dev_info(&pdev->dev, "s5p_cec_mem_probe(): mapped cec_base to %p, size %x\n", cec_base, size); return ret; } From 2012fa7971fe7239ef6a423dc1b8830a87604dc1 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Sun, 30 Jun 2013 23:21:36 +0200 Subject: [PATCH 26/30] Fill in platform_data, so that the CEC GPIO-pins get properly set --- arch/arm/mach-exynos/mach-smdk4x12.c | 20 ++++++++++++++++++++ arch/arm/plat-samsung/devs.c | 18 ++++++++++++++++++ arch/arm/plat-samsung/include/plat/hdmi.h | 10 ++++++++++ 3 files changed, 48 insertions(+) diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c index ae6da40c2aa9e1..039a8ffa5d3799 100644 --- a/arch/arm/mach-exynos/mach-smdk4x12.c +++ b/arch/arm/mach-exynos/mach-smdk4x12.c @@ -39,12 +39,19 @@ #include #include #include +#include #include #include #include "common.h" +#if defined(CONFIG_ARCH_EXYNOS4) +#define HDMI_GPX(_nr) EXYNOS4_GPX3(_nr) +#elif defined(CONFIG_ARCH_EXYNOS5) +#define HDMI_GPX(_nr) EXYNOS5_GPX3(_nr) +#endif + /* Following are default values for UCON, ULCON and UFCON UART registers */ #define SMDK4X12_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ @@ -246,6 +253,10 @@ static struct samsung_keypad_platdata smdk4x12_keypad_data __initdata = { .cols = 8, }; +static struct s5p_platform_cec hdmi_cec_data __initdata = { + +}; + #ifdef CONFIG_DRM_EXYNOS_FIMD static struct exynos_drm_fimd_pdata drm_fimd_pdata = { .panel = { @@ -332,6 +343,13 @@ static void __init smdk4x12_reserve(void) s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20); } +void s5p_cec_cfg_gpio(struct platform_device *pdev) +{ + printk(KERN_INFO "s5p_cec_cfg_gpio()\n"); + s3c_gpio_cfgpin(HDMI_GPX(6), S3C_GPIO_SFN(0x3)); + s3c_gpio_setpull(HDMI_GPX(6), S3C_GPIO_PULL_NONE); +} + static void __init smdk4x12_machine_init(void) { s3c_i2c0_set_platdata(NULL); @@ -359,6 +377,8 @@ static void __init smdk4x12_machine_init(void) s3c_sdhci3_set_platdata(&smdk4x12_hsmmc3_pdata); s3c_hsotg_set_platdata(&smdk4x12_hsotg_pdata); + + s5p_hdmi_cec_set_platdata(&hdmi_cec_data); #ifdef CONFIG_DRM_EXYNOS_FIMD s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata; diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index 36ca6043222d09..c840f7282b77a9 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c @@ -68,6 +68,8 @@ #include #include #include +#include + static u64 samsung_device_dma_mask = DMA_BIT_MASK(32); @@ -806,6 +808,22 @@ void __init s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info, #endif /* CONFIG_S5P_DEV_I2C_HDMIPHY */ +void __init s5p_hdmi_cec_set_platdata(struct s5p_platform_cec *pd) +{ + struct s5p_platform_cec *npd; + + npd = kmemdup(pd, sizeof(struct s5p_platform_cec), GFP_KERNEL); + if (!npd) + printk(KERN_ERR "%s: no memory for platform data\n", __func__); + else { + if (!npd->cfg_gpio) + npd->cfg_gpio = s5p_cec_cfg_gpio; + + s5p_device_cec.dev.platform_data = npd; + } +} + + /* I2S */ #ifdef CONFIG_PLAT_S3C24XX diff --git a/arch/arm/plat-samsung/include/plat/hdmi.h b/arch/arm/plat-samsung/include/plat/hdmi.h index 331d046ac2c574..3dcca2f493c29c 100644 --- a/arch/arm/plat-samsung/include/plat/hdmi.h +++ b/arch/arm/plat-samsung/include/plat/hdmi.h @@ -10,7 +10,17 @@ #ifndef __PLAT_SAMSUNG_HDMI_H #define __PLAT_SAMSUNG_HDMI_H __FILE__ +struct s5p_platform_cec { + + void (*cfg_gpio)(struct platform_device *pdev); +}; + extern void s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info, struct i2c_board_info *mhl_info, int mhl_bus); +extern void s5p_hdmi_cec_set_platdata(struct s5p_platform_cec *pd); + +/* defined by architecture to configure gpio */ +extern void s5p_cec_cfg_gpio(struct platform_device *pdev); + #endif /* __PLAT_SAMSUNG_HDMI_H */ From 02d365b481c3c806546029d81a26f112f8a2f576 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Mon, 1 Jul 2013 17:54:00 +0200 Subject: [PATCH 27/30] Set s5p-cec platform data on hkdk4412. Cleanup a bit --- arch/arm/mach-exynos/mach-hkdk4412.c | 7 ++++++ arch/arm/mach-exynos/mach-smdk4x12.c | 7 +++++- arch/arm/plat-samsung/devs.c | 31 +++++++++++++------------ drivers/media/platform/s5p-tv/cec_drv.c | 5 +--- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-exynos/mach-hkdk4412.c b/arch/arm/mach-exynos/mach-hkdk4412.c index f7fb7e8ab164e6..8b8a9b66f5d360 100644 --- a/arch/arm/mach-exynos/mach-hkdk4412.c +++ b/arch/arm/mach-exynos/mach-hkdk4412.c @@ -418,6 +418,12 @@ static struct platform_device *hkdk4412_devices[] __initdata = { #endif }; +#if defined(CONFIG_S5P_DEV_TV) +static struct s5p_platform_cec hdmi_cec_data __initdata = { + +}; +#endif + static void __init hkdk4412_map_io(void) { clk_xusbxti.rate = 24000000; @@ -526,6 +532,7 @@ static void __init hkdk4412_machine_init(void) s5p_tv_setup(); s5p_i2c_hdmiphy_set_platdata(NULL); s5p_hdmi_set_platdata(&hdmiphy_info, NULL, 0); + s5p_hdmi_cec_set_platdata(&hdmi_cec_data); #endif s5p_fimd0_set_platdata(&hkdk4412_fb_pdata); diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c index 039a8ffa5d3799..2a7f8afff9ee83 100644 --- a/arch/arm/mach-exynos/mach-smdk4x12.c +++ b/arch/arm/mach-exynos/mach-smdk4x12.c @@ -253,9 +253,11 @@ static struct samsung_keypad_platdata smdk4x12_keypad_data __initdata = { .cols = 8, }; +#if defined(CONFIG_S5P_DEV_TV) static struct s5p_platform_cec hdmi_cec_data __initdata = { }; +#endif #ifdef CONFIG_DRM_EXYNOS_FIMD static struct exynos_drm_fimd_pdata drm_fimd_pdata = { @@ -343,12 +345,13 @@ static void __init smdk4x12_reserve(void) s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20); } +#if defined(CONFIG_S5P_DEV_TV) void s5p_cec_cfg_gpio(struct platform_device *pdev) { - printk(KERN_INFO "s5p_cec_cfg_gpio()\n"); s3c_gpio_cfgpin(HDMI_GPX(6), S3C_GPIO_SFN(0x3)); s3c_gpio_setpull(HDMI_GPX(6), S3C_GPIO_PULL_NONE); } +#endif static void __init smdk4x12_machine_init(void) { @@ -378,7 +381,9 @@ static void __init smdk4x12_machine_init(void) s3c_hsotg_set_platdata(&smdk4x12_hsotg_pdata); +#if defined(CONFIG_S5P_DEV_TV) s5p_hdmi_cec_set_platdata(&hdmi_cec_data); +#endif #ifdef CONFIG_DRM_EXYNOS_FIMD s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata; diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index c840f7282b77a9..87d5224b8de46c 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c @@ -808,21 +808,6 @@ void __init s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info, #endif /* CONFIG_S5P_DEV_I2C_HDMIPHY */ -void __init s5p_hdmi_cec_set_platdata(struct s5p_platform_cec *pd) -{ - struct s5p_platform_cec *npd; - - npd = kmemdup(pd, sizeof(struct s5p_platform_cec), GFP_KERNEL); - if (!npd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - else { - if (!npd->cfg_gpio) - npd->cfg_gpio = s5p_cec_cfg_gpio; - - s5p_device_cec.dev.platform_data = npd; - } -} - /* I2S */ @@ -1415,6 +1400,22 @@ struct platform_device s5p_device_mixer = { .coherent_dma_mask = DMA_BIT_MASK(32), } }; + +void __init s5p_hdmi_cec_set_platdata(struct s5p_platform_cec *pd) +{ + struct s5p_platform_cec *npd; + printk(KERN_INFO "s5p_hdmi_cec_set_platdata()\n"); + + npd = kmemdup(pd, sizeof(struct s5p_platform_cec), GFP_KERNEL); + if (!npd) + printk(KERN_ERR "%s: no memory for platform data\n", __func__); + else { + if (!npd->cfg_gpio) + npd->cfg_gpio = s5p_cec_cfg_gpio; + + s5p_device_cec.dev.platform_data = npd; + } +} #endif /* CONFIG_S5P_DEV_TV */ /* USB */ diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index 530feb681e9347..1ac99bb72f75a0 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -21,10 +21,7 @@ #include #include - -struct s5p_platform_cec { - void (*cfg_gpio)(struct platform_device *pdev); -}; +#include #include "cec_hw.h" From f0c0ea37ff8589ecbea22f8259f29be297cb4fc7 Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Mon, 1 Jul 2013 18:44:56 +0200 Subject: [PATCH 28/30] cleanup --- drivers/media/platform/s5p-tv/cec_drv.c | 66 +++++++------------------ drivers/media/platform/s5p-tv/cec_hw.c | 16 +++--- 2 files changed, 26 insertions(+), 56 deletions(-) diff --git a/drivers/media/platform/s5p-tv/cec_drv.c b/drivers/media/platform/s5p-tv/cec_drv.c index 1ac99bb72f75a0..1847c9ebbae505 100644 --- a/drivers/media/platform/s5p-tv/cec_drv.c +++ b/drivers/media/platform/s5p-tv/cec_drv.c @@ -90,8 +90,6 @@ static int s5p_cec_release(struct inode *inode, struct file *file) s5p_cec_mask_rx_interrupts(); clk_disable(hdmi_cec_clk); - // clk_get() is done in probe(), so clk_put() is done in remove(), not in release(): - //clk_put(hdmi_cec_clk); return 0; } @@ -157,13 +155,10 @@ static ssize_t s5p_cec_write(struct file *file, const char __user *buffer, return -EFAULT; } - printk(KERN_INFO "\tCopying data\n"); s5p_cec_copy_packet(data, count); kfree(data); - printk(KERN_INFO "s5p_cec_write: waiting for interrupt\n"); - /* wait for interrupt */ if (wait_event_interruptible(cec_tx_struct.waitq, atomic_read(&cec_tx_struct.state) @@ -297,23 +292,22 @@ static int s5p_cec_probe(struct platform_device *pdev) int ret = 0; struct resource *res; - dev_info(dev, "probe start\n"); + dev_info(dev, "Probe start\n"); - //pdata = to_tvout_plat(&pdev->dev); pdata = to_platform_device(&pdev->dev)->dev.platform_data; - printk(KERN_INFO "s5p_cec_probe: pdata=%p\n", pdata); + dev_info(dev, "s5p_cec_probe: pdata=%p\n", pdata); if (pdata && pdata->cfg_gpio) pdata->cfg_gpio(pdev); /* get ioremap addr */ ret = s5p_cec_mem_probe(pdev); if (ret != 0) { - printk(KERN_ERR "failed to s5p_cec_mem_probe(). ret = %d\n", ret); + dev_err(dev, "Failed to s5p_cec_mem_probe(). ret = %d\n", ret); goto err_mem_probe; } if (misc_register(&cec_misc_device)) { - printk(KERN_WARNING " Couldn't register device 10, %d.\n", CEC_MINOR); + dev_err(dev, "Couldn't register device 10, %d.\n", CEC_MINOR); ret = -EBUSY; goto err_misc_register; } @@ -339,7 +333,7 @@ static int s5p_cec_probe(struct platform_device *pdev) buffer = kmalloc(CEC_TX_BUFF_SIZE, GFP_KERNEL); if (!buffer) { - printk(KERN_ERR " kmalloc() failed!\n"); + dev_err(dev, "kmalloc() failed\n"); ret = -EIO; goto err_kmalloc; } @@ -349,7 +343,7 @@ static int s5p_cec_probe(struct platform_device *pdev) hdmi_cec_clk = clk_get(&pdev->dev, "hdmicec"); if (IS_ERR(hdmi_cec_clk)) { - printk(KERN_ERR "failed to find clock 'hdmicec'\n"); + dev_err(dev, "failed to find clock 'hdmicec'\n"); ret = -ENOENT; goto err_clock; } @@ -402,21 +396,20 @@ static int s5p_cec_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int s5p_cec_suspend(struct platform_device *dev, pm_message_t state) -{ - printk(KERN_INFO "s5p_cec_suspend is a NOP\n"); - return 0; -} - -static int s5p_cec_resume(struct platform_device *dev) -{ - printk(KERN_INFO "s5p_cec_resume is a NOP\n"); - return 0; -} + static int s5p_cec_suspend(struct platform_device *dev, pm_message_t state) + { + printk(KERN_INFO "s5p_cec_suspend is a NOP\n"); + return 0; + } + static int s5p_cec_resume(struct platform_device *dev) + { + printk(KERN_INFO "s5p_cec_resume is a NOP\n"); + return 0; + } #else -#define s5p_cec_suspend NULL -#define s5p_cec_resume NULL + #define s5p_cec_suspend NULL + #define s5p_cec_resume NULL #endif static struct platform_driver s5p_cec_driver = { @@ -430,25 +423,4 @@ static struct platform_driver s5p_cec_driver = { }, }; -#if 0 - // The rest of the modules in s5p-tv do module_platform_driver() - // It makes debugging the probe a bit trickier, so don't do this now - module_platform_driver(s5p_cec_driver); -#else - static int __init s5p_cec_init(void) - { - printk(KERN_INFO "S5P CEC for TVOUT Driver, Copyright (c) 2011 Samsung Electronics Co., LTD.\n"); - request_module("s5p-hdmi"); - return platform_driver_register(&s5p_cec_driver); - } - - static void __exit s5p_cec_exit(void) - { - printk(KERN_INFO "S5P CEC for TVOUT Driver, exiting\n"); - //kfree(cec_rx_struct.buffer); // moved to s5p_cec_remove() - platform_driver_unregister(&s5p_cec_driver); - } - - module_init(s5p_cec_init); - module_exit(s5p_cec_exit); -#endif +module_platform_driver(s5p_cec_driver); diff --git a/drivers/media/platform/s5p-tv/cec_hw.c b/drivers/media/platform/s5p-tv/cec_hw.c index e6b3cae316ab56..108e5b3da04bc3 100644 --- a/drivers/media/platform/s5p-tv/cec_hw.c +++ b/drivers/media/platform/s5p-tv/cec_hw.c @@ -14,10 +14,9 @@ #include #include -//#include // doesn't seem to work #include "cec_hw.h" -#include "regs-cec.h" // somehow mach/regs-cec.h isn't picked up +#include "regs-cec.h" #define S5P_HDMI_FIN 24000000 #define CEC_DIV_RATIO 320000 @@ -153,7 +152,6 @@ void s5p_cec_copy_packet(char *data, size_t count) else reg &= ~S5P_CEC_TX_CTRL_BCAST; - printk(KERN_INFO "s5p_cec_copy_packet(): flagging S5P_CEC_TX_CTRL\n"); reg |= 0x50; writeb(reg, cec_base + S5P_CEC_TX_CTRL); } @@ -206,34 +204,34 @@ int s5p_cec_mem_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(&pdev->dev, - "failed to get memory region resource for cec\n"); + "Failed to get memory region resource for cec\n"); return -ENOENT; } else size = resource_size(res); cec_mem = request_mem_region(res->start, size, pdev->name); if (cec_mem == NULL) { - dev_err(&pdev->dev, "failed to get memory at size %i, name %s\n", size, pdev->name); + dev_err(&pdev->dev, "Failed to get memory at size %i, name %s\n", size, pdev->name); return -ENOENT; } cec_base = ioremap(res->start, size); if (cec_base == NULL) { dev_err(&pdev->dev, - "failed to ioremap address region for cec\n"); + "Failed to ioremap address region for cec\n"); return -ENOENT; } - dev_info(&pdev->dev, "s5p_cec_mem_probe(): mapped cec_base to %p, size %x\n", cec_base, size); + dev_info(&pdev->dev, "s5p_cec_mem_probe(): mapped cec_base to %p, size 0x%x\n", cec_base, size); return ret; } int s5p_cec_mem_release(struct platform_device *pdev) { - dev_info(&pdev->dev, "releasing memory\n"); + dev_info(&pdev->dev, "Releasing memory\n"); iounmap(cec_base); if (cec_mem != NULL) { if (release_resource(cec_mem)) - dev_err(&pdev->dev, "can't remove s5p-cec driver !!\n"); + dev_err(&pdev->dev, "Can't remove s5p-cec driver\n"); kfree(cec_mem); From 785289f54aed726655f871394b8cbe5b68792dbf Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Mon, 1 Jul 2013 18:50:05 +0200 Subject: [PATCH 29/30] status update --- README | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README b/README index 35da98f06d9e46..ceaca518ade76e 100644 --- a/README +++ b/README @@ -1,7 +1,8 @@ Summary: - Trying to get CEC (tv-remote control over HDMI) working on linux. - There appear to be android-kernel sources. - The hardkernel linux-tree doesn't have those + Get CEC (tv-remote control over HDMI) working on linux. + There are android-kernel sources, which have not made it + to the main linux kernel-tree, so also the hardkernel + linux-tree doesn't have CEC for exynos platforms. Status: Copied s5p-cec code from all over the internet, mostly from @@ -10,11 +11,11 @@ Status: Fixed the insmod()/rmmod() stuff. Error handling and resource free-ing were quite broken. - cec-client recognizes the device, have not seen data yet: + Using a modified cec-client, it's possible to observe the + tv changing it's inputs, see: https://github.com/vamanea/libcec.git TODO: - Try to read/write some data to /dev/CEC Cleanup this tree, so it becomes a nice diff upon hardkernel's 3.8 tree From d58c60f4506f58c77b4cc94867ca1e308feb51bd Mon Sep 17 00:00:00 2001 From: Thijs Withaar Date: Mon, 1 Jul 2013 19:02:42 +0200 Subject: [PATCH 30/30] cleanup --- arch/arm/mach-s5pv210/include/mach/map.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h index de994e08989e07..824b73423672c6 100644 --- a/arch/arm/mach-s5pv210/include/mach/map.h +++ b/arch/arm/mach-s5pv210/include/mach/map.h @@ -49,8 +49,6 @@ #define S5PV210_PA_PCM2 0xE2B00000 #define S5PV210_PA_CEC 0xE1B00000 -#define S5P_PA_CEC S5PV210_PA_CEC -#define S5P_SZ_CEC SZ_4K #define S5PV210_PA_TIMER 0xE2500000 #define S5PV210_PA_SYSTIMER 0xE2600000 @@ -130,6 +128,8 @@ #define S5P_PA_VP S5PV210_PA_VP #define S5P_PA_MIXER S5PV210_PA_MIXER #define S5P_PA_HDMI S5PV210_PA_HDMI +#define S5P_PA_CEC S5PV210_PA_CEC +#define S5P_SZ_CEC SZ_4K #define S5P_PA_ONENAND S5PC110_PA_ONENAND #define S5P_PA_ONENAND_DMA S5PC110_PA_ONENAND_DMA