-
Notifications
You must be signed in to change notification settings - Fork 5.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
vc4_hdmi: Add CEC support for 2711 #3601
Changes from all commits
c91e9a2
6073eb2
3a51340
5a28d49
c3d9165
47948ef
e5735e2
80c1ffd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -79,6 +79,7 @@ | |
# define VC4_HD_M_ENABLE BIT(0) | ||
|
||
#define CEC_CLOCK_FREQ 40000 | ||
#define VC4_HSM_CLOCK 163682864 | ||
|
||
static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) | ||
{ | ||
|
@@ -755,8 +756,7 @@ static u32 vc4_hdmi_calc_hsm_clock(struct vc4_hdmi *vc4_hdmi, unsigned long pixe | |
* needs to be a bit higher than the pixel clock rate | ||
* (generally 148.5Mhz). | ||
*/ | ||
|
||
return 163682864; | ||
return VC4_HSM_CLOCK; | ||
} | ||
|
||
static u32 vc5_hdmi_calc_hsm_clock(struct vc4_hdmi *vc4_hdmi, unsigned long pixel_rate) | ||
|
@@ -1264,8 +1264,13 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1) | |
|
||
msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >> | ||
VC4_HDMI_CEC_REC_WRD_CNT_SHIFT); | ||
|
||
if (msg->len > 16) { | ||
DRM_ERROR("Attempting to read too much data (%d)\n", msg->len); | ||
return; | ||
} | ||
for (i = 0; i < msg->len; i += 4) { | ||
u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + i); | ||
u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + (i>>2)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this correct for Pi3 as well? It appears to be unconditional on revision. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes it is a bug on Pi3. Any long messages would trample other registers (and we are getting longer messages in log). |
||
|
||
msg->msg[i] = val & 0xff; | ||
msg->msg[i + 1] = (val >> 8) & 0xff; | ||
|
@@ -1280,7 +1285,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) | |
u32 stat = HDMI_READ(HDMI_CEC_CPU_STATUS); | ||
u32 cntrl1, cntrl5; | ||
|
||
if (!(stat & VC4_HDMI_CPU_CEC)) | ||
if (!(stat & vc4_hdmi->variant->cec_mask)) | ||
return IRQ_NONE; | ||
vc4_hdmi->cec_rx_msg.len = 0; | ||
cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1); | ||
|
@@ -1296,7 +1301,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) | |
cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN; | ||
} | ||
HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1); | ||
HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC); | ||
HDMI_WRITE(HDMI_CEC_CPU_CLEAR, vc4_hdmi->variant->cec_mask); | ||
|
||
return IRQ_WAKE_THREAD; | ||
} | ||
|
@@ -1335,9 +1340,9 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) | |
((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) | | ||
((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT)); | ||
|
||
HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC); | ||
HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, vc4_hdmi->variant->cec_mask); | ||
} else { | ||
HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC); | ||
HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, vc4_hdmi->variant->cec_mask); | ||
HDMI_WRITE(HDMI_CEC_CNTRL_5, val | | ||
VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET); | ||
} | ||
|
@@ -1361,8 +1366,12 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, | |
u32 val; | ||
unsigned int i; | ||
|
||
pelwell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (msg->len > 16) { | ||
DRM_ERROR("Attempting to transmit too much data (%d)\n", msg->len); | ||
return -ENOMEM; | ||
} | ||
for (i = 0; i < msg->len; i += 4) | ||
HDMI_WRITE(HDMI_CEC_TX_DATA_1 + i, | ||
HDMI_WRITE(HDMI_CEC_TX_DATA_1 + (i>>2), | ||
(msg->msg[i]) | | ||
(msg->msg[i + 1] << 8) | | ||
(msg->msg[i + 2] << 16) | | ||
|
@@ -1390,11 +1399,9 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) | |
struct cec_connector_info conn_info; | ||
struct platform_device *pdev = vc4_hdmi->pdev; | ||
u32 value; | ||
u32 clk_cnt; | ||
int ret; | ||
|
||
if (!vc4_hdmi->variant->cec_available) | ||
return 0; | ||
|
||
vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, | ||
vc4_hdmi, "vc4", | ||
CEC_CAP_DEFAULTS | | ||
|
@@ -1414,12 +1421,14 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) | |
* divider: the hsm_clock rate and this divider setting will | ||
* give a 40 kHz CEC clock. | ||
*/ | ||
clk_cnt = vc4_hdmi->variant->cec_input_clock / CEC_CLOCK_FREQ; | ||
value |= VC4_HDMI_CEC_ADDR_MASK | | ||
(4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT); | ||
((clk_cnt-1) << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT); | ||
HDMI_WRITE(HDMI_CEC_CNTRL_1, value); | ||
ret = devm_request_threaded_irq(&pdev->dev, platform_get_irq(pdev, 0), | ||
vc4_cec_irq_handler, | ||
vc4_cec_irq_handler_thread, 0, | ||
vc4_cec_irq_handler_thread, | ||
IRQF_SHARED, | ||
"vc4 hdmi cec", vc4_hdmi); | ||
if (ret) | ||
goto err_delete_cec_adap; | ||
|
@@ -1572,6 +1581,14 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) | |
if (IS_ERR(vc4_hdmi->dvp_regs)) | ||
return PTR_ERR(vc4_hdmi->dvp_regs); | ||
|
||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr2"); | ||
if (!res) | ||
return -ENODEV; | ||
|
||
vc4_hdmi->intr2_regs = devm_ioremap(dev, res->start, resource_size(res)); | ||
pelwell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (IS_ERR(vc4_hdmi->intr2_regs)) | ||
return PTR_ERR(vc4_hdmi->intr2_regs); | ||
|
||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); | ||
if (!res) | ||
return -ENODEV; | ||
|
@@ -1751,8 +1768,8 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev) | |
|
||
static const struct vc4_hdmi_variant bcm2835_variant = { | ||
.max_pixel_clock = 162000000, | ||
.cec_input_clock = VC4_HSM_CLOCK, | ||
.audio_available = true, | ||
.cec_available = true, | ||
.registers = vc4_hdmi_fields, | ||
.num_registers = ARRAY_SIZE(vc4_hdmi_fields), | ||
|
||
|
@@ -1767,12 +1784,15 @@ static const struct vc4_hdmi_variant bcm2835_variant = { | |
.get_hsm_clock = vc4_hdmi_get_hsm_clock, | ||
.calc_hsm_clock = vc4_hdmi_calc_hsm_clock, | ||
.channel_map = vc4_hdmi_channel_map, | ||
|
||
.cec_mask = VC4_HDMI_CPU_CEC, | ||
}; | ||
|
||
static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = { | ||
.id = 0, | ||
.audio_available = true, | ||
.max_pixel_clock = 297000000, | ||
.cec_input_clock = 27000000, | ||
.registers = vc5_hdmi_hdmi0_fields, | ||
.num_registers = ARRAY_SIZE(vc5_hdmi_hdmi0_fields), | ||
.phy_lane_mapping = { | ||
|
@@ -1792,12 +1812,15 @@ static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = { | |
.get_hsm_clock = vc5_hdmi_get_hsm_clock, | ||
.calc_hsm_clock = vc5_hdmi_calc_hsm_clock, | ||
.channel_map = vc5_hdmi_channel_map, | ||
|
||
.cec_mask = VC5_HDMI0_CPU_CEC_RX | VC5_HDMI0_CPU_CEC_TX, | ||
}; | ||
|
||
static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = { | ||
.id = 1, | ||
.audio_available = true, | ||
.max_pixel_clock = 297000000, | ||
.cec_input_clock = 27000000, | ||
.registers = vc5_hdmi_hdmi1_fields, | ||
.num_registers = ARRAY_SIZE(vc5_hdmi_hdmi1_fields), | ||
.phy_lane_mapping = { | ||
|
@@ -1817,6 +1840,8 @@ static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = { | |
.get_hsm_clock = vc5_hdmi_get_hsm_clock, | ||
.calc_hsm_clock = vc5_hdmi_calc_hsm_clock, | ||
.channel_map = vc5_hdmi_channel_map, | ||
|
||
.cec_mask = VC5_HDMI1_CPU_CEC_RX | VC5_HDMI1_CPU_CEC_TX, | ||
}; | ||
|
||
static const struct of_device_id vc4_hdmi_dt_match[] = { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this not also applicable to 64-bit builds?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Untested but no reason I can think of why 64-bit build would fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throw it in there, then.