.. | .. |
---|
27 | 27 | #include <linux/videodev2.h> |
---|
28 | 28 | #include <linux/workqueue.h> |
---|
29 | 29 | #include <linux/regmap.h> |
---|
| 30 | +#include <linux/interrupt.h> |
---|
30 | 31 | |
---|
31 | 32 | #include <media/i2c/adv7604.h> |
---|
32 | 33 | #include <media/cec.h> |
---|
.. | .. |
---|
113 | 114 | unsigned int tdms_lock_mask; |
---|
114 | 115 | unsigned int fmt_change_digital_mask; |
---|
115 | 116 | unsigned int cp_csc; |
---|
| 117 | + |
---|
| 118 | + unsigned int cec_irq_status; |
---|
| 119 | + unsigned int cec_rx_enable; |
---|
| 120 | + unsigned int cec_rx_enable_mask; |
---|
| 121 | + bool cec_irq_swap; |
---|
116 | 122 | |
---|
117 | 123 | const struct adv76xx_format_info *formats; |
---|
118 | 124 | unsigned int nformats; |
---|
.. | .. |
---|
1497 | 1503 | |
---|
1498 | 1504 | static unsigned int adv7604_read_hdmi_pixelclock(struct v4l2_subdev *sd) |
---|
1499 | 1505 | { |
---|
1500 | | - unsigned int freq; |
---|
1501 | 1506 | int a, b; |
---|
1502 | 1507 | |
---|
1503 | 1508 | a = hdmi_read(sd, 0x06); |
---|
1504 | 1509 | b = hdmi_read(sd, 0x3b); |
---|
1505 | 1510 | if (a < 0 || b < 0) |
---|
1506 | 1511 | return 0; |
---|
1507 | | - freq = a * 1000000 + ((b & 0x30) >> 4) * 250000; |
---|
1508 | 1512 | |
---|
1509 | | - if (is_hdmi(sd)) { |
---|
1510 | | - /* adjust for deep color mode */ |
---|
1511 | | - unsigned bits_per_channel = ((hdmi_read(sd, 0x0b) & 0x60) >> 4) + 8; |
---|
1512 | | - |
---|
1513 | | - freq = freq * 8 / bits_per_channel; |
---|
1514 | | - } |
---|
1515 | | - |
---|
1516 | | - return freq; |
---|
| 1513 | + return a * 1000000 + ((b & 0x30) >> 4) * 250000; |
---|
1517 | 1514 | } |
---|
1518 | 1515 | |
---|
1519 | 1516 | static unsigned int adv7611_read_hdmi_pixelclock(struct v4l2_subdev *sd) |
---|
.. | .. |
---|
1524 | 1521 | b = hdmi_read(sd, 0x52); |
---|
1525 | 1522 | if (a < 0 || b < 0) |
---|
1526 | 1523 | return 0; |
---|
| 1524 | + |
---|
1527 | 1525 | return ((a << 1) | (b >> 7)) * 1000000 + (b & 0x7f) * 1000000 / 128; |
---|
| 1526 | +} |
---|
| 1527 | + |
---|
| 1528 | +static unsigned int adv76xx_read_hdmi_pixelclock(struct v4l2_subdev *sd) |
---|
| 1529 | +{ |
---|
| 1530 | + struct adv76xx_state *state = to_state(sd); |
---|
| 1531 | + const struct adv76xx_chip_info *info = state->info; |
---|
| 1532 | + unsigned int freq, bits_per_channel, pixelrepetition; |
---|
| 1533 | + |
---|
| 1534 | + freq = info->read_hdmi_pixelclock(sd); |
---|
| 1535 | + if (is_hdmi(sd)) { |
---|
| 1536 | + /* adjust for deep color mode and pixel repetition */ |
---|
| 1537 | + bits_per_channel = ((hdmi_read(sd, 0x0b) & 0x60) >> 4) + 8; |
---|
| 1538 | + pixelrepetition = (hdmi_read(sd, 0x05) & 0x0f) + 1; |
---|
| 1539 | + |
---|
| 1540 | + freq = freq * 8 / bits_per_channel / pixelrepetition; |
---|
| 1541 | + } |
---|
| 1542 | + |
---|
| 1543 | + return freq; |
---|
1528 | 1544 | } |
---|
1529 | 1545 | |
---|
1530 | 1546 | static int adv76xx_query_dv_timings(struct v4l2_subdev *sd, |
---|
.. | .. |
---|
1573 | 1589 | |
---|
1574 | 1590 | bt->width = w; |
---|
1575 | 1591 | bt->height = h; |
---|
1576 | | - bt->pixelclock = info->read_hdmi_pixelclock(sd); |
---|
| 1592 | + bt->pixelclock = adv76xx_read_hdmi_pixelclock(sd); |
---|
1577 | 1593 | bt->hfrontporch = hdmi_read16(sd, 0x20, info->hfrontporch_mask); |
---|
1578 | 1594 | bt->hsync = hdmi_read16(sd, 0x22, info->hsync_mask); |
---|
1579 | 1595 | bt->hbackporch = hdmi_read16(sd, 0x24, info->hbackporch_mask); |
---|
.. | .. |
---|
2003 | 2019 | static void adv76xx_cec_isr(struct v4l2_subdev *sd, bool *handled) |
---|
2004 | 2020 | { |
---|
2005 | 2021 | struct adv76xx_state *state = to_state(sd); |
---|
| 2022 | + const struct adv76xx_chip_info *info = state->info; |
---|
2006 | 2023 | u8 cec_irq; |
---|
2007 | 2024 | |
---|
2008 | 2025 | /* cec controller */ |
---|
2009 | | - cec_irq = io_read(sd, 0x4d) & 0x0f; |
---|
| 2026 | + cec_irq = io_read(sd, info->cec_irq_status) & 0x0f; |
---|
2010 | 2027 | if (!cec_irq) |
---|
2011 | 2028 | return; |
---|
2012 | 2029 | |
---|
.. | .. |
---|
2024 | 2041 | |
---|
2025 | 2042 | for (i = 0; i < msg.len; i++) |
---|
2026 | 2043 | msg.msg[i] = cec_read(sd, i + 0x15); |
---|
2027 | | - cec_write(sd, 0x26, 0x01); /* re-enable rx */ |
---|
| 2044 | + cec_write(sd, info->cec_rx_enable, |
---|
| 2045 | + info->cec_rx_enable_mask); /* re-enable rx */ |
---|
2028 | 2046 | cec_received_msg(state->cec_adap, &msg); |
---|
2029 | 2047 | } |
---|
2030 | 2048 | } |
---|
2031 | 2049 | |
---|
2032 | | - /* note: the bit order is swapped between 0x4d and 0x4e */ |
---|
2033 | | - cec_irq = ((cec_irq & 0x08) >> 3) | ((cec_irq & 0x04) >> 1) | |
---|
2034 | | - ((cec_irq & 0x02) << 1) | ((cec_irq & 0x01) << 3); |
---|
2035 | | - io_write(sd, 0x4e, cec_irq); |
---|
| 2050 | + if (info->cec_irq_swap) { |
---|
| 2051 | + /* |
---|
| 2052 | + * Note: the bit order is swapped between 0x4d and 0x4e |
---|
| 2053 | + * on adv7604 |
---|
| 2054 | + */ |
---|
| 2055 | + cec_irq = ((cec_irq & 0x08) >> 3) | ((cec_irq & 0x04) >> 1) | |
---|
| 2056 | + ((cec_irq & 0x02) << 1) | ((cec_irq & 0x01) << 3); |
---|
| 2057 | + } |
---|
| 2058 | + io_write(sd, info->cec_irq_status + 1, cec_irq); |
---|
2036 | 2059 | |
---|
2037 | 2060 | if (handled) |
---|
2038 | 2061 | *handled = true; |
---|
.. | .. |
---|
2041 | 2064 | static int adv76xx_cec_adap_enable(struct cec_adapter *adap, bool enable) |
---|
2042 | 2065 | { |
---|
2043 | 2066 | struct adv76xx_state *state = cec_get_drvdata(adap); |
---|
| 2067 | + const struct adv76xx_chip_info *info = state->info; |
---|
2044 | 2068 | struct v4l2_subdev *sd = &state->sd; |
---|
2045 | 2069 | |
---|
2046 | 2070 | if (!state->cec_enabled_adap && enable) { |
---|
.. | .. |
---|
2052 | 2076 | /* tx: arbitration lost */ |
---|
2053 | 2077 | /* tx: retry timeout */ |
---|
2054 | 2078 | /* rx: ready */ |
---|
2055 | | - io_write_clr_set(sd, 0x50, 0x0f, 0x0f); |
---|
2056 | | - cec_write(sd, 0x26, 0x01); /* enable rx */ |
---|
| 2079 | + io_write_clr_set(sd, info->cec_irq_status + 3, 0x0f, 0x0f); |
---|
| 2080 | + cec_write(sd, info->cec_rx_enable, info->cec_rx_enable_mask); |
---|
2057 | 2081 | } else if (state->cec_enabled_adap && !enable) { |
---|
2058 | 2082 | /* disable cec interrupts */ |
---|
2059 | | - io_write_clr_set(sd, 0x50, 0x0f, 0x00); |
---|
| 2083 | + io_write_clr_set(sd, info->cec_irq_status + 3, 0x0f, 0x00); |
---|
2060 | 2084 | /* disable address mask 1-3 */ |
---|
2061 | 2085 | cec_write_clr_set(sd, 0x27, 0x70, 0x00); |
---|
2062 | 2086 | /* power down cec section */ |
---|
.. | .. |
---|
2219 | 2243 | *handled = true; |
---|
2220 | 2244 | } |
---|
2221 | 2245 | return 0; |
---|
| 2246 | +} |
---|
| 2247 | + |
---|
| 2248 | +static irqreturn_t adv76xx_irq_handler(int irq, void *dev_id) |
---|
| 2249 | +{ |
---|
| 2250 | + struct adv76xx_state *state = dev_id; |
---|
| 2251 | + bool handled = false; |
---|
| 2252 | + |
---|
| 2253 | + adv76xx_isr(&state->sd, 0, &handled); |
---|
| 2254 | + |
---|
| 2255 | + return handled ? IRQ_HANDLED : IRQ_NONE; |
---|
2222 | 2256 | } |
---|
2223 | 2257 | |
---|
2224 | 2258 | static int adv76xx_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) |
---|
.. | .. |
---|
2420 | 2454 | buffer[i + 3] = infoframe_read(sd, |
---|
2421 | 2455 | adv76xx_cri[index].payload_addr + i); |
---|
2422 | 2456 | |
---|
2423 | | - if (hdmi_infoframe_unpack(frame, buffer, sizeof(buffer)) < 0) { |
---|
| 2457 | + if (hdmi_infoframe_unpack(frame, buffer, len + 3) < 0) { |
---|
2424 | 2458 | v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, |
---|
2425 | 2459 | adv76xx_cri[index].desc); |
---|
2426 | 2460 | return -ENOENT; |
---|
.. | .. |
---|
2838 | 2872 | { |
---|
2839 | 2873 | unsigned int i; |
---|
2840 | 2874 | |
---|
2841 | | - for (i = 1; i < ARRAY_SIZE(state->i2c_clients); ++i) { |
---|
2842 | | - if (state->i2c_clients[i]) |
---|
2843 | | - i2c_unregister_device(state->i2c_clients[i]); |
---|
2844 | | - } |
---|
| 2875 | + for (i = 1; i < ARRAY_SIZE(state->i2c_clients); ++i) |
---|
| 2876 | + i2c_unregister_device(state->i2c_clients[i]); |
---|
2845 | 2877 | } |
---|
2846 | 2878 | |
---|
2847 | 2879 | static struct i2c_client *adv76xx_dummy_client(struct v4l2_subdev *sd, |
---|
.. | .. |
---|
2854 | 2886 | struct i2c_client *new_client; |
---|
2855 | 2887 | |
---|
2856 | 2888 | if (pdata && pdata->i2c_addresses[page]) |
---|
2857 | | - new_client = i2c_new_dummy(client->adapter, |
---|
| 2889 | + new_client = i2c_new_dummy_device(client->adapter, |
---|
2858 | 2890 | pdata->i2c_addresses[page]); |
---|
2859 | 2891 | else |
---|
2860 | | - new_client = i2c_new_secondary_device(client, |
---|
| 2892 | + new_client = i2c_new_ancillary_device(client, |
---|
2861 | 2893 | adv76xx_default_addresses[page].name, |
---|
2862 | 2894 | adv76xx_default_addresses[page].default_addr); |
---|
2863 | 2895 | |
---|
2864 | | - if (new_client) |
---|
| 2896 | + if (!IS_ERR(new_client)) |
---|
2865 | 2897 | io_write(sd, io_reg, new_client->addr << 1); |
---|
2866 | 2898 | |
---|
2867 | 2899 | return new_client; |
---|
.. | .. |
---|
2960 | 2992 | .cable_det_mask = 0x1e, |
---|
2961 | 2993 | .fmt_change_digital_mask = 0xc1, |
---|
2962 | 2994 | .cp_csc = 0xfc, |
---|
| 2995 | + .cec_irq_status = 0x4d, |
---|
| 2996 | + .cec_rx_enable = 0x26, |
---|
| 2997 | + .cec_rx_enable_mask = 0x01, |
---|
| 2998 | + .cec_irq_swap = true, |
---|
2963 | 2999 | .formats = adv7604_formats, |
---|
2964 | 3000 | .nformats = ARRAY_SIZE(adv7604_formats), |
---|
2965 | 3001 | .set_termination = adv7604_set_termination, |
---|
.. | .. |
---|
3006 | 3042 | .cable_det_mask = 0x01, |
---|
3007 | 3043 | .fmt_change_digital_mask = 0x03, |
---|
3008 | 3044 | .cp_csc = 0xf4, |
---|
| 3045 | + .cec_irq_status = 0x93, |
---|
| 3046 | + .cec_rx_enable = 0x2c, |
---|
| 3047 | + .cec_rx_enable_mask = 0x02, |
---|
3009 | 3048 | .formats = adv7611_formats, |
---|
3010 | 3049 | .nformats = ARRAY_SIZE(adv7611_formats), |
---|
3011 | 3050 | .set_termination = adv7611_set_termination, |
---|
.. | .. |
---|
3047 | 3086 | .cable_det_mask = 0x01, |
---|
3048 | 3087 | .fmt_change_digital_mask = 0x03, |
---|
3049 | 3088 | .cp_csc = 0xf4, |
---|
| 3089 | + .cec_irq_status = 0x93, |
---|
| 3090 | + .cec_rx_enable = 0x2c, |
---|
| 3091 | + .cec_rx_enable_mask = 0x02, |
---|
3050 | 3092 | .formats = adv7612_formats, |
---|
3051 | 3093 | .nformats = ARRAY_SIZE(adv7612_formats), |
---|
3052 | 3094 | .set_termination = adv7611_set_termination, |
---|
.. | .. |
---|
3095 | 3137 | |
---|
3096 | 3138 | static int adv76xx_parse_dt(struct adv76xx_state *state) |
---|
3097 | 3139 | { |
---|
3098 | | - struct v4l2_fwnode_endpoint bus_cfg; |
---|
| 3140 | + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; |
---|
3099 | 3141 | struct device_node *endpoint; |
---|
3100 | 3142 | struct device_node *np; |
---|
3101 | 3143 | unsigned int flags; |
---|
.. | .. |
---|
3134 | 3176 | state->pdata.insert_av_codes = 1; |
---|
3135 | 3177 | |
---|
3136 | 3178 | /* Disable the interrupt for now as no DT-based board uses it. */ |
---|
3137 | | - state->pdata.int1_config = ADV76XX_INT1_CONFIG_DISABLED; |
---|
| 3179 | + state->pdata.int1_config = ADV76XX_INT1_CONFIG_ACTIVE_HIGH; |
---|
3138 | 3180 | |
---|
3139 | 3181 | /* Hardcode the remaining platform data fields. */ |
---|
3140 | 3182 | state->pdata.disable_pwrdnb = 0; |
---|
.. | .. |
---|
3482 | 3524 | } |
---|
3483 | 3525 | |
---|
3484 | 3526 | for (i = 1; i < ADV76XX_PAGE_MAX; ++i) { |
---|
| 3527 | + struct i2c_client *dummy_client; |
---|
| 3528 | + |
---|
3485 | 3529 | if (!(BIT(i) & state->info->page_mask)) |
---|
3486 | 3530 | continue; |
---|
3487 | 3531 | |
---|
3488 | | - state->i2c_clients[i] = adv76xx_dummy_client(sd, i); |
---|
3489 | | - if (!state->i2c_clients[i]) { |
---|
3490 | | - err = -EINVAL; |
---|
| 3532 | + dummy_client = adv76xx_dummy_client(sd, i); |
---|
| 3533 | + if (IS_ERR(dummy_client)) { |
---|
| 3534 | + err = PTR_ERR(dummy_client); |
---|
3491 | 3535 | v4l2_err(sd, "failed to create i2c client %u\n", i); |
---|
3492 | 3536 | goto err_i2c; |
---|
3493 | 3537 | } |
---|
| 3538 | + |
---|
| 3539 | + state->i2c_clients[i] = dummy_client; |
---|
3494 | 3540 | } |
---|
3495 | 3541 | |
---|
3496 | 3542 | INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug, |
---|
.. | .. |
---|
3517 | 3563 | if (err) |
---|
3518 | 3564 | goto err_entity; |
---|
3519 | 3565 | |
---|
| 3566 | + if (client->irq) { |
---|
| 3567 | + err = devm_request_threaded_irq(&client->dev, |
---|
| 3568 | + client->irq, |
---|
| 3569 | + NULL, adv76xx_irq_handler, |
---|
| 3570 | + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, |
---|
| 3571 | + client->name, state); |
---|
| 3572 | + if (err) |
---|
| 3573 | + goto err_entity; |
---|
| 3574 | + } |
---|
| 3575 | + |
---|
3520 | 3576 | #if IS_ENABLED(CONFIG_VIDEO_ADV7604_CEC) |
---|
3521 | 3577 | state->cec_adap = cec_allocate_adapter(&adv76xx_cec_adap_ops, |
---|
3522 | 3578 | state, dev_name(&client->dev), |
---|