Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'drm-misc-next-2017-10-12' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

More 4.15 drm-misc stuff:

Cross-subsystem Changes:
- bridge cleanup refactor (Benjamin Gaignard)

Core Changes:
- less surprising atomic iterators (Maarten), fixes an oops introduced
in drm-next
- better gem/fb helper docs (Noralf)
- fix dma-buf rcu races (Christian König)

Driver Changes:
- adv7511: CEC support (Hans Verkuil)
- sun4i update from Chen-Yu to improve hdmi and A31 support
- sii8620: add remote control support (Maceiej Purski)

New drivers:
- SiI9234 bridge driver (Maciej Purski)
- 7" rpi touch panel (Eric Anholt)

Note that this contains a topic pull from regmap, needed by the sun4i
changes. Mark Brown sent that out for pulling into drm-misc.

* tag 'drm-misc-next-2017-10-12' of git://anongit.freedesktop.org/drm/drm-misc: (29 commits)
drm/dp: WARN about invalid/unknown link rates and bw codes
drm/msm/mdp5: remove less than 0 comparison for unsigned value
drm/bridge/sii8620: add remote control support
drm/sun4i: hdmi: Add support for A31's HDMI controller
drm/sun4i: hdmi: Add A31 specific DDC register definitions
drm/sun4i: hdmi: Add support for controller hardware variants
dt-bindings: display: sun4i: Add binding for A31 HDMI controller
drm/sun4i: hdmi: Allow using second PLL as TMDS clk parent
drm/sun4i: hdmi: create a regmap for later use
drm/sun4i: hdmi: Disable clks in bind function error path and unbind function
drm/sun4i: tcon: Add support for demuxing TCON output on A31
drm/sun4i: tcon: Add variant callback for TCON output muxing
drm/bridge/synopsys: dsi :remove is_panel_bridge
drm/vc4: remove bridge from driver internal structure
drm/stm: ltdc: remove bridge from driver internal structure
drm/drm_of: add drm_of_panel_bridge_remove function
drm/bridge: make drm_panel_bridge_remove more robust
dma-fence: fix dma_fence_get_rcu_safe v2
dma-buf: make reservation_object_copy_fences rcu save
drm/atomic: Unref duplicated drm_atomic_state in drm_atomic_helper_resume()
...

+3057 -332
+4
Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt
··· 68 68 - adi,disable-timing-generator: Only for ADV7533. Disables the internal timing 69 69 generator. The chip will rely on the sync signals in the DSI data lanes, 70 70 rather than generate its own timings for HDMI output. 71 + - clocks: from common clock binding: reference to the CEC clock. 72 + - clock-names: from common clock binding: must be "cec". 71 73 72 74 Required nodes: 73 75 ··· 91 89 reg = <39>; 92 90 interrupt-parent = <&gpio3>; 93 91 interrupts = <29 IRQ_TYPE_EDGE_FALLING>; 92 + clocks = <&cec_clock>; 93 + clock-names = "cec"; 94 94 95 95 adi,input-depth = <8>; 96 96 adi,input-colorspace = "rgb";
+49
Documentation/devicetree/bindings/display/bridge/sii9234.txt
··· 1 + Silicon Image SiI9234 HDMI/MHL bridge bindings 2 + 3 + Required properties: 4 + - compatible : "sil,sii9234". 5 + - reg : I2C address for TPI interface, use 0x39 6 + - avcc33-supply : MHL/USB Switch Supply Voltage (3.3V) 7 + - iovcc18-supply : I/O Supply Voltage (1.8V) 8 + - avcc12-supply : TMDS Analog Supply Voltage (1.2V) 9 + - cvcc12-supply : Digital Core Supply Voltage (1.2V) 10 + - interrupts, interrupt-parent: interrupt specifier of INT pin 11 + - reset-gpios: gpio specifier of RESET pin (active low) 12 + - video interfaces: Device node can contain two video interface port 13 + nodes for HDMI encoder and connector according to [1]. 14 + - port@0 - MHL to HDMI 15 + - port@1 - MHL to connector 16 + 17 + [1]: Documentation/devicetree/bindings/media/video-interfaces.txt 18 + 19 + 20 + Example: 21 + sii9234@39 { 22 + compatible = "sil,sii9234"; 23 + reg = <0x39>; 24 + avcc33-supply = <&vcc33mhl>; 25 + iovcc18-supply = <&vcc18mhl>; 26 + avcc12-supply = <&vsil12>; 27 + cvcc12-supply = <&vsil12>; 28 + reset-gpios = <&gpf3 4 GPIO_ACTIVE_LOW>; 29 + interrupt-parent = <&gpf3>; 30 + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; 31 + 32 + ports { 33 + #address-cells = <1>; 34 + #size-cells = <0>; 35 + 36 + port@0 { 37 + reg = <0>; 38 + mhl_to_hdmi: endpoint { 39 + remote-endpoint = <&hdmi_to_mhl>; 40 + }; 41 + }; 42 + port@1 { 43 + reg = <1>; 44 + mhl_to_connector: endpoint { 45 + remote-endpoint = <&connector_to_mhl>; 46 + }; 47 + }; 48 + }; 49 + };
+49
Documentation/devicetree/bindings/display/panel/raspberrypi,7inch-touchscreen.txt
··· 1 + This binding covers the official 7" (800x480) Raspberry Pi touchscreen 2 + panel. 3 + 4 + This DSI panel contains: 5 + 6 + - TC358762 DSI->DPI bridge 7 + - Atmel microcontroller on I2C for power sequencing the DSI bridge and 8 + controlling backlight 9 + - Touchscreen controller on I2C for touch input 10 + 11 + and this binding covers the DSI display parts but not its touch input. 12 + 13 + Required properties: 14 + - compatible: Must be "raspberrypi,7inch-touchscreen-panel" 15 + - reg: Must be "45" 16 + - port: See panel-common.txt 17 + 18 + Example: 19 + 20 + dsi1: dsi@7e700000 { 21 + #address-cells = <1>; 22 + #size-cells = <0>; 23 + <...> 24 + 25 + port { 26 + dsi_out_port: endpoint { 27 + remote-endpoint = <&panel_dsi_port>; 28 + }; 29 + }; 30 + }; 31 + 32 + i2c_dsi: i2c { 33 + compatible = "i2c-gpio"; 34 + #address-cells = <1>; 35 + #size-cells = <0>; 36 + gpios = <&gpio 28 0 37 + &gpio 29 0>; 38 + 39 + lcd@45 { 40 + compatible = "raspberrypi,7inch-touchscreen-panel"; 41 + reg = <0x45>; 42 + 43 + port { 44 + panel_dsi_port: endpoint { 45 + remote-endpoint = <&dsi_out_port>; 46 + }; 47 + }; 48 + }; 49 + };
+3
Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
··· 41 41 Required properties: 42 42 - compatible: value must be one of: 43 43 * allwinner,sun5i-a10s-hdmi 44 + * allwinner,sun6i-a31-hdmi 44 45 - reg: base address and size of memory-mapped region 45 46 - interrupts: interrupt associated to this IP 46 47 - clocks: phandles to the clocks feeding the HDMI encoder 47 48 * ahb: the HDMI interface clock 48 49 * mod: the HDMI module clock 50 + * ddc: the HDMI ddc clock (A31 only) 49 51 * pll-0: the first video PLL 50 52 * pll-1: the second video PLL 51 53 - clock-names: the clock names mentioned above 54 + - resets: phandle to the reset control for the HDMI encoder (A31 only) 52 55 - dmas: phandles to the DMA channels used by the HDMI encoder 53 56 * ddc-tx: The channel for DDC transmission 54 57 * ddc-rx: The channel for DDC reception
+42 -14
drivers/dma-buf/reservation.c
··· 266 266 * @dst: the destination reservation object 267 267 * @src: the source reservation object 268 268 * 269 - * Copy all fences from src to dst. Both src->lock as well as dst-lock must be 270 - * held. 269 + * Copy all fences from src to dst. dst-lock must be held. 271 270 */ 272 271 int reservation_object_copy_fences(struct reservation_object *dst, 273 272 struct reservation_object *src) ··· 276 277 size_t size; 277 278 unsigned i; 278 279 279 - src_list = reservation_object_get_list(src); 280 + rcu_read_lock(); 281 + src_list = rcu_dereference(src->fence); 280 282 283 + retry: 281 284 if (src_list) { 282 - size = offsetof(typeof(*src_list), 283 - shared[src_list->shared_count]); 285 + unsigned shared_count = src_list->shared_count; 286 + 287 + size = offsetof(typeof(*src_list), shared[shared_count]); 288 + rcu_read_unlock(); 289 + 284 290 dst_list = kmalloc(size, GFP_KERNEL); 285 291 if (!dst_list) 286 292 return -ENOMEM; 287 293 288 - dst_list->shared_count = src_list->shared_count; 289 - dst_list->shared_max = src_list->shared_count; 290 - for (i = 0; i < src_list->shared_count; ++i) 291 - dst_list->shared[i] = 292 - dma_fence_get(src_list->shared[i]); 294 + rcu_read_lock(); 295 + src_list = rcu_dereference(src->fence); 296 + if (!src_list || src_list->shared_count > shared_count) { 297 + kfree(dst_list); 298 + goto retry; 299 + } 300 + 301 + dst_list->shared_count = 0; 302 + dst_list->shared_max = shared_count; 303 + for (i = 0; i < src_list->shared_count; ++i) { 304 + struct dma_fence *fence; 305 + 306 + fence = rcu_dereference(src_list->shared[i]); 307 + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, 308 + &fence->flags)) 309 + continue; 310 + 311 + if (!dma_fence_get_rcu(fence)) { 312 + kfree(dst_list); 313 + src_list = rcu_dereference(src->fence); 314 + goto retry; 315 + } 316 + 317 + if (dma_fence_is_signaled(fence)) { 318 + dma_fence_put(fence); 319 + continue; 320 + } 321 + 322 + dst_list->shared[dst_list->shared_count++] = fence; 323 + } 293 324 } else { 294 325 dst_list = NULL; 295 326 } 327 + 328 + new = dma_fence_get_rcu_safe(&src->fence_excl); 329 + rcu_read_unlock(); 296 330 297 331 kfree(dst->staged); 298 332 dst->staged = NULL; 299 333 300 334 src_list = reservation_object_get_list(dst); 301 - 302 335 old = reservation_object_get_excl(dst); 303 - new = reservation_object_get_excl(src); 304 - 305 - dma_fence_get(new); 306 336 307 337 preempt_disable(); 308 338 write_seqcount_begin(&dst->seq);
+9 -1
drivers/gpu/drm/bridge/Kconfig
··· 71 71 72 72 config DRM_SIL_SII8620 73 73 tristate "Silicon Image SII8620 HDMI/MHL bridge" 74 - depends on OF 74 + depends on OF && RC_CORE 75 75 select DRM_KMS_HELPER 76 76 help 77 77 Silicon Image SII8620 HDMI/MHL bridge chip driver. ··· 83 83 select REGMAP_I2C 84 84 ---help--- 85 85 Silicon Image sii902x bridge chip driver. 86 + 87 + config DRM_SII9234 88 + tristate "Silicon Image SII9234 HDMI/MHL bridge" 89 + depends on OF 90 + ---help--- 91 + Say Y here if you want support for the MHL interface. 92 + It is an I2C driver, that detects connection of MHL bridge 93 + and starts encapsulation of HDMI signal. 86 94 87 95 config DRM_TOSHIBA_TC358767 88 96 tristate "Toshiba TC358767 eDP bridge"
+1
drivers/gpu/drm/bridge/Makefile
··· 6 6 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o 7 7 obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o 8 8 obj-$(CONFIG_DRM_SII902X) += sii902x.o 9 + obj-$(CONFIG_DRM_SII9234) += sii9234.o 9 10 obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o 10 11 obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/ 11 12 obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
+8
drivers/gpu/drm/bridge/adv7511/Kconfig
··· 21 21 default y 22 22 help 23 23 Support for the Analog Devices ADV7533 DSI to HDMI encoder. 24 + 25 + config DRM_I2C_ADV7511_CEC 26 + bool "ADV7511/33 HDMI CEC driver" 27 + depends on DRM_I2C_ADV7511 28 + select CEC_CORE 29 + default y 30 + help 31 + When selected the HDMI transmitter will support the CEC feature.
+1
drivers/gpu/drm/bridge/adv7511/Makefile
··· 1 1 adv7511-y := adv7511_drv.o 2 2 adv7511-$(CONFIG_DRM_I2C_ADV7511_AUDIO) += adv7511_audio.o 3 + adv7511-$(CONFIG_DRM_I2C_ADV7511_CEC) += adv7511_cec.o 3 4 adv7511-$(CONFIG_DRM_I2C_ADV7533) += adv7533.o 4 5 obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511.o
+36 -7
drivers/gpu/drm/bridge/adv7511/adv7511.h
··· 195 195 #define ADV7511_PACKET_GM(x) ADV7511_PACKET(5, x) 196 196 #define ADV7511_PACKET_SPARE(x) ADV7511_PACKET(6, x) 197 197 198 + #define ADV7511_REG_CEC_TX_FRAME_HDR 0x00 199 + #define ADV7511_REG_CEC_TX_FRAME_DATA0 0x01 200 + #define ADV7511_REG_CEC_TX_FRAME_LEN 0x10 201 + #define ADV7511_REG_CEC_TX_ENABLE 0x11 202 + #define ADV7511_REG_CEC_TX_RETRY 0x12 203 + #define ADV7511_REG_CEC_TX_LOW_DRV_CNT 0x14 204 + #define ADV7511_REG_CEC_RX_FRAME_HDR 0x15 205 + #define ADV7511_REG_CEC_RX_FRAME_DATA0 0x16 206 + #define ADV7511_REG_CEC_RX_FRAME_LEN 0x25 207 + #define ADV7511_REG_CEC_RX_ENABLE 0x26 208 + #define ADV7511_REG_CEC_RX_BUFFERS 0x4a 209 + #define ADV7511_REG_CEC_LOG_ADDR_MASK 0x4b 210 + #define ADV7511_REG_CEC_LOG_ADDR_0_1 0x4c 211 + #define ADV7511_REG_CEC_LOG_ADDR_2 0x4d 212 + #define ADV7511_REG_CEC_CLK_DIV 0x4e 213 + #define ADV7511_REG_CEC_SOFT_RESET 0x50 214 + 215 + #define ADV7533_REG_CEC_OFFSET 0x70 216 + 198 217 enum adv7511_input_clock { 199 218 ADV7511_INPUT_CLOCK_1X, 200 219 ADV7511_INPUT_CLOCK_2X, ··· 316 297 ADV7533, 317 298 }; 318 299 300 + #define ADV7511_MAX_ADDRS 3 301 + 319 302 struct adv7511 { 320 303 struct i2c_client *i2c_main; 321 304 struct i2c_client *i2c_edid; ··· 362 341 363 342 enum adv7511_type type; 364 343 struct platform_device *audio_pdev; 344 + 345 + struct cec_adapter *cec_adap; 346 + u8 cec_addr[ADV7511_MAX_ADDRS]; 347 + u8 cec_valid_addrs; 348 + bool cec_enabled_adap; 349 + struct clk *cec_clk; 350 + u32 cec_clk_freq; 365 351 }; 352 + 353 + #ifdef CONFIG_DRM_I2C_ADV7511_CEC 354 + int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511, 355 + unsigned int offset); 356 + void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1); 357 + #endif 366 358 367 359 #ifdef CONFIG_DRM_I2C_ADV7533 368 360 void adv7533_dsi_power_on(struct adv7511 *adv); 369 361 void adv7533_dsi_power_off(struct adv7511 *adv); 370 362 void adv7533_mode_set(struct adv7511 *adv, struct drm_display_mode *mode); 371 363 int adv7533_patch_registers(struct adv7511 *adv); 372 - void adv7533_uninit_cec(struct adv7511 *adv); 373 - int adv7533_init_cec(struct adv7511 *adv); 364 + int adv7533_patch_cec_registers(struct adv7511 *adv); 374 365 int adv7533_attach_dsi(struct adv7511 *adv); 375 366 void adv7533_detach_dsi(struct adv7511 *adv); 376 367 int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv); ··· 405 372 return -ENODEV; 406 373 } 407 374 408 - static inline void adv7533_uninit_cec(struct adv7511 *adv) 409 - { 410 - } 411 - 412 - static inline int adv7533_init_cec(struct adv7511 *adv) 375 + static inline int adv7533_patch_cec_registers(struct adv7511 *adv) 413 376 { 414 377 return -ENODEV; 415 378 }
+337
drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
··· 1 + /* 2 + * adv7511_cec.c - Analog Devices ADV7511/33 cec driver 3 + * 4 + * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 5 + * 6 + * This program is free software; you may redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; version 2 of the License. 9 + * 10 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 11 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 12 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 13 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 14 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 15 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 + * SOFTWARE. 18 + * 19 + */ 20 + 21 + #include <linux/device.h> 22 + #include <linux/module.h> 23 + #include <linux/of_device.h> 24 + #include <linux/slab.h> 25 + #include <linux/clk.h> 26 + 27 + #include <media/cec.h> 28 + 29 + #include "adv7511.h" 30 + 31 + #define ADV7511_INT1_CEC_MASK \ 32 + (ADV7511_INT1_CEC_TX_READY | ADV7511_INT1_CEC_TX_ARBIT_LOST | \ 33 + ADV7511_INT1_CEC_TX_RETRY_TIMEOUT | ADV7511_INT1_CEC_RX_READY1) 34 + 35 + static void adv_cec_tx_raw_status(struct adv7511 *adv7511, u8 tx_raw_status) 36 + { 37 + unsigned int offset = adv7511->type == ADV7533 ? 38 + ADV7533_REG_CEC_OFFSET : 0; 39 + unsigned int val; 40 + 41 + if (regmap_read(adv7511->regmap_cec, 42 + ADV7511_REG_CEC_TX_ENABLE + offset, &val)) 43 + return; 44 + 45 + if ((val & 0x01) == 0) 46 + return; 47 + 48 + if (tx_raw_status & ADV7511_INT1_CEC_TX_ARBIT_LOST) { 49 + cec_transmit_attempt_done(adv7511->cec_adap, 50 + CEC_TX_STATUS_ARB_LOST); 51 + return; 52 + } 53 + if (tx_raw_status & ADV7511_INT1_CEC_TX_RETRY_TIMEOUT) { 54 + u8 status; 55 + u8 err_cnt = 0; 56 + u8 nack_cnt = 0; 57 + u8 low_drive_cnt = 0; 58 + unsigned int cnt; 59 + 60 + /* 61 + * We set this status bit since this hardware performs 62 + * retransmissions. 63 + */ 64 + status = CEC_TX_STATUS_MAX_RETRIES; 65 + if (regmap_read(adv7511->regmap_cec, 66 + ADV7511_REG_CEC_TX_LOW_DRV_CNT + offset, &cnt)) { 67 + err_cnt = 1; 68 + status |= CEC_TX_STATUS_ERROR; 69 + } else { 70 + nack_cnt = cnt & 0xf; 71 + if (nack_cnt) 72 + status |= CEC_TX_STATUS_NACK; 73 + low_drive_cnt = cnt >> 4; 74 + if (low_drive_cnt) 75 + status |= CEC_TX_STATUS_LOW_DRIVE; 76 + } 77 + cec_transmit_done(adv7511->cec_adap, status, 78 + 0, nack_cnt, low_drive_cnt, err_cnt); 79 + return; 80 + } 81 + if (tx_raw_status & ADV7511_INT1_CEC_TX_READY) { 82 + cec_transmit_attempt_done(adv7511->cec_adap, CEC_TX_STATUS_OK); 83 + return; 84 + } 85 + } 86 + 87 + void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1) 88 + { 89 + unsigned int offset = adv7511->type == ADV7533 ? 90 + ADV7533_REG_CEC_OFFSET : 0; 91 + const u32 irq_tx_mask = ADV7511_INT1_CEC_TX_READY | 92 + ADV7511_INT1_CEC_TX_ARBIT_LOST | 93 + ADV7511_INT1_CEC_TX_RETRY_TIMEOUT; 94 + struct cec_msg msg = {}; 95 + unsigned int len; 96 + unsigned int val; 97 + u8 i; 98 + 99 + if (irq1 & irq_tx_mask) 100 + adv_cec_tx_raw_status(adv7511, irq1); 101 + 102 + if (!(irq1 & ADV7511_INT1_CEC_RX_READY1)) 103 + return; 104 + 105 + if (regmap_read(adv7511->regmap_cec, 106 + ADV7511_REG_CEC_RX_FRAME_LEN + offset, &len)) 107 + return; 108 + 109 + msg.len = len & 0x1f; 110 + 111 + if (msg.len > 16) 112 + msg.len = 16; 113 + 114 + if (!msg.len) 115 + return; 116 + 117 + for (i = 0; i < msg.len; i++) { 118 + regmap_read(adv7511->regmap_cec, 119 + i + ADV7511_REG_CEC_RX_FRAME_HDR + offset, &val); 120 + msg.msg[i] = val; 121 + } 122 + 123 + /* toggle to re-enable rx 1 */ 124 + regmap_write(adv7511->regmap_cec, 125 + ADV7511_REG_CEC_RX_BUFFERS + offset, 1); 126 + regmap_write(adv7511->regmap_cec, 127 + ADV7511_REG_CEC_RX_BUFFERS + offset, 0); 128 + cec_received_msg(adv7511->cec_adap, &msg); 129 + } 130 + 131 + static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable) 132 + { 133 + struct adv7511 *adv7511 = cec_get_drvdata(adap); 134 + unsigned int offset = adv7511->type == ADV7533 ? 135 + ADV7533_REG_CEC_OFFSET : 0; 136 + 137 + if (adv7511->i2c_cec == NULL) 138 + return -EIO; 139 + 140 + if (!adv7511->cec_enabled_adap && enable) { 141 + /* power up cec section */ 142 + regmap_update_bits(adv7511->regmap_cec, 143 + ADV7511_REG_CEC_CLK_DIV + offset, 144 + 0x03, 0x01); 145 + /* legacy mode and clear all rx buffers */ 146 + regmap_write(adv7511->regmap_cec, 147 + ADV7511_REG_CEC_RX_BUFFERS + offset, 0x07); 148 + regmap_write(adv7511->regmap_cec, 149 + ADV7511_REG_CEC_RX_BUFFERS + offset, 0); 150 + /* initially disable tx */ 151 + regmap_update_bits(adv7511->regmap_cec, 152 + ADV7511_REG_CEC_TX_ENABLE + offset, 1, 0); 153 + /* enabled irqs: */ 154 + /* tx: ready */ 155 + /* tx: arbitration lost */ 156 + /* tx: retry timeout */ 157 + /* rx: ready 1 */ 158 + regmap_update_bits(adv7511->regmap, 159 + ADV7511_REG_INT_ENABLE(1), 0x3f, 160 + ADV7511_INT1_CEC_MASK); 161 + } else if (adv7511->cec_enabled_adap && !enable) { 162 + regmap_update_bits(adv7511->regmap, 163 + ADV7511_REG_INT_ENABLE(1), 0x3f, 0); 164 + /* disable address mask 1-3 */ 165 + regmap_update_bits(adv7511->regmap_cec, 166 + ADV7511_REG_CEC_LOG_ADDR_MASK + offset, 167 + 0x70, 0x00); 168 + /* power down cec section */ 169 + regmap_update_bits(adv7511->regmap_cec, 170 + ADV7511_REG_CEC_CLK_DIV + offset, 171 + 0x03, 0x00); 172 + adv7511->cec_valid_addrs = 0; 173 + } 174 + adv7511->cec_enabled_adap = enable; 175 + return 0; 176 + } 177 + 178 + static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr) 179 + { 180 + struct adv7511 *adv7511 = cec_get_drvdata(adap); 181 + unsigned int offset = adv7511->type == ADV7533 ? 182 + ADV7533_REG_CEC_OFFSET : 0; 183 + unsigned int i, free_idx = ADV7511_MAX_ADDRS; 184 + 185 + if (!adv7511->cec_enabled_adap) 186 + return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO; 187 + 188 + if (addr == CEC_LOG_ADDR_INVALID) { 189 + regmap_update_bits(adv7511->regmap_cec, 190 + ADV7511_REG_CEC_LOG_ADDR_MASK + offset, 191 + 0x70, 0); 192 + adv7511->cec_valid_addrs = 0; 193 + return 0; 194 + } 195 + 196 + for (i = 0; i < ADV7511_MAX_ADDRS; i++) { 197 + bool is_valid = adv7511->cec_valid_addrs & (1 << i); 198 + 199 + if (free_idx == ADV7511_MAX_ADDRS && !is_valid) 200 + free_idx = i; 201 + if (is_valid && adv7511->cec_addr[i] == addr) 202 + return 0; 203 + } 204 + if (i == ADV7511_MAX_ADDRS) { 205 + i = free_idx; 206 + if (i == ADV7511_MAX_ADDRS) 207 + return -ENXIO; 208 + } 209 + adv7511->cec_addr[i] = addr; 210 + adv7511->cec_valid_addrs |= 1 << i; 211 + 212 + switch (i) { 213 + case 0: 214 + /* enable address mask 0 */ 215 + regmap_update_bits(adv7511->regmap_cec, 216 + ADV7511_REG_CEC_LOG_ADDR_MASK + offset, 217 + 0x10, 0x10); 218 + /* set address for mask 0 */ 219 + regmap_update_bits(adv7511->regmap_cec, 220 + ADV7511_REG_CEC_LOG_ADDR_0_1 + offset, 221 + 0x0f, addr); 222 + break; 223 + case 1: 224 + /* enable address mask 1 */ 225 + regmap_update_bits(adv7511->regmap_cec, 226 + ADV7511_REG_CEC_LOG_ADDR_MASK + offset, 227 + 0x20, 0x20); 228 + /* set address for mask 1 */ 229 + regmap_update_bits(adv7511->regmap_cec, 230 + ADV7511_REG_CEC_LOG_ADDR_0_1 + offset, 231 + 0xf0, addr << 4); 232 + break; 233 + case 2: 234 + /* enable address mask 2 */ 235 + regmap_update_bits(adv7511->regmap_cec, 236 + ADV7511_REG_CEC_LOG_ADDR_MASK + offset, 237 + 0x40, 0x40); 238 + /* set address for mask 1 */ 239 + regmap_update_bits(adv7511->regmap_cec, 240 + ADV7511_REG_CEC_LOG_ADDR_2 + offset, 241 + 0x0f, addr); 242 + break; 243 + } 244 + return 0; 245 + } 246 + 247 + static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, 248 + u32 signal_free_time, struct cec_msg *msg) 249 + { 250 + struct adv7511 *adv7511 = cec_get_drvdata(adap); 251 + unsigned int offset = adv7511->type == ADV7533 ? 252 + ADV7533_REG_CEC_OFFSET : 0; 253 + u8 len = msg->len; 254 + unsigned int i; 255 + 256 + /* 257 + * The number of retries is the number of attempts - 1, but retry 258 + * at least once. It's not clear if a value of 0 is allowed, so 259 + * let's do at least one retry. 260 + */ 261 + regmap_update_bits(adv7511->regmap_cec, 262 + ADV7511_REG_CEC_TX_RETRY + offset, 263 + 0x70, max(1, attempts - 1) << 4); 264 + 265 + /* blocking, clear cec tx irq status */ 266 + regmap_update_bits(adv7511->regmap, ADV7511_REG_INT(1), 0x38, 0x38); 267 + 268 + /* write data */ 269 + for (i = 0; i < len; i++) 270 + regmap_write(adv7511->regmap_cec, 271 + i + ADV7511_REG_CEC_TX_FRAME_HDR + offset, 272 + msg->msg[i]); 273 + 274 + /* set length (data + header) */ 275 + regmap_write(adv7511->regmap_cec, 276 + ADV7511_REG_CEC_TX_FRAME_LEN + offset, len); 277 + /* start transmit, enable tx */ 278 + regmap_write(adv7511->regmap_cec, 279 + ADV7511_REG_CEC_TX_ENABLE + offset, 0x01); 280 + return 0; 281 + } 282 + 283 + static const struct cec_adap_ops adv7511_cec_adap_ops = { 284 + .adap_enable = adv7511_cec_adap_enable, 285 + .adap_log_addr = adv7511_cec_adap_log_addr, 286 + .adap_transmit = adv7511_cec_adap_transmit, 287 + }; 288 + 289 + static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511) 290 + { 291 + adv7511->cec_clk = devm_clk_get(dev, "cec"); 292 + if (IS_ERR(adv7511->cec_clk)) { 293 + int ret = PTR_ERR(adv7511->cec_clk); 294 + 295 + adv7511->cec_clk = NULL; 296 + return ret; 297 + } 298 + clk_prepare_enable(adv7511->cec_clk); 299 + adv7511->cec_clk_freq = clk_get_rate(adv7511->cec_clk); 300 + return 0; 301 + } 302 + 303 + int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511, 304 + unsigned int offset) 305 + { 306 + int ret = adv7511_cec_parse_dt(dev, adv7511); 307 + 308 + if (ret) 309 + return ret; 310 + 311 + adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops, 312 + adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS); 313 + if (IS_ERR(adv7511->cec_adap)) 314 + return PTR_ERR(adv7511->cec_adap); 315 + 316 + regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0); 317 + /* cec soft reset */ 318 + regmap_write(adv7511->regmap_cec, 319 + ADV7511_REG_CEC_SOFT_RESET + offset, 0x01); 320 + regmap_write(adv7511->regmap_cec, 321 + ADV7511_REG_CEC_SOFT_RESET + offset, 0x00); 322 + 323 + /* legacy mode */ 324 + regmap_write(adv7511->regmap_cec, 325 + ADV7511_REG_CEC_RX_BUFFERS + offset, 0x00); 326 + 327 + regmap_write(adv7511->regmap_cec, 328 + ADV7511_REG_CEC_CLK_DIV + offset, 329 + ((adv7511->cec_clk_freq / 750000) - 1) << 2); 330 + 331 + ret = cec_register_adapter(adv7511->cec_adap, dev); 332 + if (ret) { 333 + cec_delete_adapter(adv7511->cec_adap); 334 + adv7511->cec_adap = NULL; 335 + } 336 + return ret; 337 + }
+101 -15
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
··· 11 11 #include <linux/module.h> 12 12 #include <linux/of_device.h> 13 13 #include <linux/slab.h> 14 + #include <linux/clk.h> 14 15 15 16 #include <drm/drmP.h> 16 17 #include <drm/drm_atomic.h> 17 18 #include <drm/drm_atomic_helper.h> 18 19 #include <drm/drm_edid.h> 20 + 21 + #include <media/cec.h> 19 22 20 23 #include "adv7511.h" 21 24 ··· 339 336 */ 340 337 regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0), 341 338 ADV7511_INT0_EDID_READY | ADV7511_INT0_HPD); 342 - regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1), 343 - ADV7511_INT1_DDC_ERROR); 339 + regmap_update_bits(adv7511->regmap, 340 + ADV7511_REG_INT_ENABLE(1), 341 + ADV7511_INT1_DDC_ERROR, 342 + ADV7511_INT1_DDC_ERROR); 344 343 } 345 344 346 345 /* ··· 378 373 regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, 379 374 ADV7511_POWER_POWER_DOWN, 380 375 ADV7511_POWER_POWER_DOWN); 376 + regmap_update_bits(adv7511->regmap, 377 + ADV7511_REG_INT_ENABLE(1), 378 + ADV7511_INT1_DDC_ERROR, 0); 381 379 regcache_mark_dirty(adv7511->regmap); 382 380 } 383 381 ··· 431 423 432 424 if (adv7511->connector.status != status) { 433 425 adv7511->connector.status = status; 426 + if (status == connector_status_disconnected) 427 + cec_phys_addr_invalidate(adv7511->cec_adap); 434 428 drm_kms_helper_hotplug_event(adv7511->connector.dev); 435 429 } 436 430 } ··· 462 452 if (adv7511->i2c_main->irq) 463 453 wake_up_all(&adv7511->wq); 464 454 } 455 + 456 + #ifdef CONFIG_DRM_I2C_ADV7511_CEC 457 + adv7511_cec_irq_process(adv7511, irq1); 458 + #endif 465 459 466 460 return 0; 467 461 } ··· 608 594 drm_detect_hdmi_monitor(edid)); 609 595 610 596 kfree(edid); 597 + 598 + cec_s_phys_addr_from_edid(adv7511->cec_adap, edid); 611 599 612 600 return count; 613 601 } ··· 935 919 regulator_bulk_disable(adv->num_supplies, adv->supplies); 936 920 } 937 921 922 + static bool adv7511_cec_register_volatile(struct device *dev, unsigned int reg) 923 + { 924 + struct i2c_client *i2c = to_i2c_client(dev); 925 + struct adv7511 *adv7511 = i2c_get_clientdata(i2c); 926 + 927 + if (adv7511->type == ADV7533) 928 + reg -= ADV7533_REG_CEC_OFFSET; 929 + 930 + switch (reg) { 931 + case ADV7511_REG_CEC_RX_FRAME_HDR: 932 + case ADV7511_REG_CEC_RX_FRAME_DATA0... 933 + ADV7511_REG_CEC_RX_FRAME_DATA0 + 14: 934 + case ADV7511_REG_CEC_RX_FRAME_LEN: 935 + case ADV7511_REG_CEC_RX_BUFFERS: 936 + case ADV7511_REG_CEC_TX_LOW_DRV_CNT: 937 + return true; 938 + } 939 + 940 + return false; 941 + } 942 + 943 + static const struct regmap_config adv7511_cec_regmap_config = { 944 + .reg_bits = 8, 945 + .val_bits = 8, 946 + 947 + .max_register = 0xff, 948 + .cache_type = REGCACHE_RBTREE, 949 + .volatile_reg = adv7511_cec_register_volatile, 950 + }; 951 + 952 + static int adv7511_init_cec_regmap(struct adv7511 *adv) 953 + { 954 + int ret; 955 + 956 + adv->i2c_cec = i2c_new_dummy(adv->i2c_main->adapter, 957 + adv->i2c_main->addr - 1); 958 + if (!adv->i2c_cec) 959 + return -ENOMEM; 960 + i2c_set_clientdata(adv->i2c_cec, adv); 961 + 962 + adv->regmap_cec = devm_regmap_init_i2c(adv->i2c_cec, 963 + &adv7511_cec_regmap_config); 964 + if (IS_ERR(adv->regmap_cec)) { 965 + ret = PTR_ERR(adv->regmap_cec); 966 + goto err; 967 + } 968 + 969 + if (adv->type == ADV7533) { 970 + ret = adv7533_patch_cec_registers(adv); 971 + if (ret) 972 + goto err; 973 + } 974 + 975 + return 0; 976 + err: 977 + i2c_unregister_device(adv->i2c_cec); 978 + return ret; 979 + } 980 + 938 981 static int adv7511_parse_dt(struct device_node *np, 939 982 struct adv7511_link_config *config) 940 983 { ··· 1084 1009 struct device *dev = &i2c->dev; 1085 1010 unsigned int main_i2c_addr = i2c->addr << 1; 1086 1011 unsigned int edid_i2c_addr = main_i2c_addr + 4; 1012 + unsigned int offset; 1087 1013 unsigned int val; 1088 1014 int ret; 1089 1015 ··· 1168 1092 goto uninit_regulators; 1169 1093 } 1170 1094 1171 - if (adv7511->type == ADV7533) { 1172 - ret = adv7533_init_cec(adv7511); 1173 - if (ret) 1174 - goto err_i2c_unregister_edid; 1175 - } 1095 + ret = adv7511_init_cec_regmap(adv7511); 1096 + if (ret) 1097 + goto err_i2c_unregister_edid; 1176 1098 1177 1099 INIT_WORK(&adv7511->hpd_work, adv7511_hpd_work); 1178 1100 ··· 1184 1110 if (ret) 1185 1111 goto err_unregister_cec; 1186 1112 } 1187 - 1188 - /* CEC is unused for now */ 1189 - regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, 1190 - ADV7511_CEC_CTRL_POWER_DOWN); 1191 1113 1192 1114 adv7511_power_off(adv7511); 1193 1115 ··· 1199 1129 1200 1130 adv7511_audio_init(dev, adv7511); 1201 1131 1132 + offset = adv7511->type == ADV7533 ? ADV7533_REG_CEC_OFFSET : 0; 1133 + 1134 + #ifdef CONFIG_DRM_I2C_ADV7511_CEC 1135 + ret = adv7511_cec_init(dev, adv7511, offset); 1136 + if (ret) 1137 + goto err_unregister_cec; 1138 + #else 1139 + regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 1140 + ADV7511_CEC_CTRL_POWER_DOWN); 1141 + #endif 1142 + 1202 1143 return 0; 1203 1144 1204 1145 err_unregister_cec: 1205 - adv7533_uninit_cec(adv7511); 1146 + i2c_unregister_device(adv7511->i2c_cec); 1147 + if (adv7511->cec_clk) 1148 + clk_disable_unprepare(adv7511->cec_clk); 1206 1149 err_i2c_unregister_edid: 1207 1150 i2c_unregister_device(adv7511->i2c_edid); 1208 1151 uninit_regulators: ··· 1228 1145 { 1229 1146 struct adv7511 *adv7511 = i2c_get_clientdata(i2c); 1230 1147 1231 - if (adv7511->type == ADV7533) { 1148 + if (adv7511->type == ADV7533) 1232 1149 adv7533_detach_dsi(adv7511); 1233 - adv7533_uninit_cec(adv7511); 1234 - } 1150 + i2c_unregister_device(adv7511->i2c_cec); 1151 + if (adv7511->cec_clk) 1152 + clk_disable_unprepare(adv7511->cec_clk); 1235 1153 1236 1154 adv7511_uninit_regulators(adv7511); 1237 1155 1238 1156 drm_bridge_remove(&adv7511->bridge); 1239 1157 1240 1158 adv7511_audio_exit(adv7511); 1159 + 1160 + cec_unregister_adapter(adv7511->cec_adap); 1241 1161 1242 1162 i2c_unregister_device(adv7511->i2c_edid); 1243 1163
+2 -36
drivers/gpu/drm/bridge/adv7511/adv7533.c
··· 32 32 { 0x05, 0xc8 }, 33 33 }; 34 34 35 - static const struct regmap_config adv7533_cec_regmap_config = { 36 - .reg_bits = 8, 37 - .val_bits = 8, 38 - 39 - .max_register = 0xff, 40 - .cache_type = REGCACHE_RBTREE, 41 - }; 42 - 43 35 static void adv7511_dsi_config_timing_gen(struct adv7511 *adv) 44 36 { 45 37 struct mipi_dsi_device *dsi = adv->dsi; ··· 137 145 ARRAY_SIZE(adv7533_fixed_registers)); 138 146 } 139 147 140 - void adv7533_uninit_cec(struct adv7511 *adv) 148 + int adv7533_patch_cec_registers(struct adv7511 *adv) 141 149 { 142 - i2c_unregister_device(adv->i2c_cec); 143 - } 144 - 145 - int adv7533_init_cec(struct adv7511 *adv) 146 - { 147 - int ret; 148 - 149 - adv->i2c_cec = i2c_new_dummy(adv->i2c_main->adapter, 150 - adv->i2c_main->addr - 1); 151 - if (!adv->i2c_cec) 152 - return -ENOMEM; 153 - 154 - adv->regmap_cec = devm_regmap_init_i2c(adv->i2c_cec, 155 - &adv7533_cec_regmap_config); 156 - if (IS_ERR(adv->regmap_cec)) { 157 - ret = PTR_ERR(adv->regmap_cec); 158 - goto err; 159 - } 160 - 161 - ret = regmap_register_patch(adv->regmap_cec, 150 + return regmap_register_patch(adv->regmap_cec, 162 151 adv7533_cec_fixed_registers, 163 152 ARRAY_SIZE(adv7533_cec_fixed_registers)); 164 - if (ret) 165 - goto err; 166 - 167 - return 0; 168 - err: 169 - adv7533_uninit_cec(adv); 170 - return ret; 171 153 } 172 154 173 155 int adv7533_attach_dsi(struct adv7511 *adv)
+9 -1
drivers/gpu/drm/bridge/panel.c
··· 188 188 */ 189 189 void drm_panel_bridge_remove(struct drm_bridge *bridge) 190 190 { 191 - struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); 191 + struct panel_bridge *panel_bridge; 192 + 193 + if (!bridge) 194 + return; 195 + 196 + if (bridge->funcs != &panel_bridge_bridge_funcs) 197 + return; 198 + 199 + panel_bridge = drm_bridge_to_panel_bridge(bridge); 192 200 193 201 drm_bridge_remove(bridge); 194 202 devm_kfree(panel_bridge->panel->dev, bridge);
+994
drivers/gpu/drm/bridge/sii9234.c
··· 1 + /* 2 + * Copyright (C) 2017 Samsung Electronics 3 + * 4 + * Authors: 5 + * Tomasz Stanislawski <t.stanislaws@samsung.com> 6 + * Maciej Purski <m.purski@samsung.com> 7 + * 8 + * Based on sii9234 driver created by: 9 + * Adam Hampson <ahampson@sta.samsung.com> 10 + * Erik Gilling <konkers@android.com> 11 + * Shankar Bandal <shankar.b@samsung.com> 12 + * Dharam Kumar <dharam.kr@samsung.com> 13 + * 14 + * This program is free software; you can redistribute it and/or modify 15 + * it under the terms of the GNU General Public License as published by 16 + * the Free Software Foundation; either version 2 of the License, or 17 + * (at your option) any later version. 18 + * 19 + * This program is distributed in the hope that it will be useful, 20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 + * GNU General Public License for more details. 23 + * 24 + * You should have received a copy of the GNU General Public License 25 + * along with this program 26 + * 27 + */ 28 + #include <drm/bridge/mhl.h> 29 + #include <drm/drm_crtc.h> 30 + #include <drm/drm_edid.h> 31 + 32 + #include <linux/delay.h> 33 + #include <linux/err.h> 34 + #include <linux/gpio/consumer.h> 35 + #include <linux/i2c.h> 36 + #include <linux/interrupt.h> 37 + #include <linux/irq.h> 38 + #include <linux/kernel.h> 39 + #include <linux/module.h> 40 + #include <linux/mutex.h> 41 + #include <linux/regulator/consumer.h> 42 + #include <linux/slab.h> 43 + 44 + #define CBUS_DEVCAP_OFFSET 0x80 45 + 46 + #define SII9234_MHL_VERSION 0x11 47 + #define SII9234_SCRATCHPAD_SIZE 0x10 48 + #define SII9234_INT_STAT_SIZE 0x33 49 + 50 + #define BIT_TMDS_CCTRL_TMDS_OE BIT(4) 51 + #define MHL_HPD_OUT_OVR_EN BIT(4) 52 + #define MHL_HPD_OUT_OVR_VAL BIT(5) 53 + #define MHL_INIT_TIMEOUT 0x0C 54 + 55 + /* MHL Tx registers and bits */ 56 + #define MHL_TX_SRST 0x05 57 + #define MHL_TX_SYSSTAT_REG 0x09 58 + #define MHL_TX_INTR1_REG 0x71 59 + #define MHL_TX_INTR4_REG 0x74 60 + #define MHL_TX_INTR1_ENABLE_REG 0x75 61 + #define MHL_TX_INTR4_ENABLE_REG 0x78 62 + #define MHL_TX_INT_CTRL_REG 0x79 63 + #define MHL_TX_TMDS_CCTRL 0x80 64 + #define MHL_TX_DISC_CTRL1_REG 0x90 65 + #define MHL_TX_DISC_CTRL2_REG 0x91 66 + #define MHL_TX_DISC_CTRL3_REG 0x92 67 + #define MHL_TX_DISC_CTRL4_REG 0x93 68 + #define MHL_TX_DISC_CTRL5_REG 0x94 69 + #define MHL_TX_DISC_CTRL6_REG 0x95 70 + #define MHL_TX_DISC_CTRL7_REG 0x96 71 + #define MHL_TX_DISC_CTRL8_REG 0x97 72 + #define MHL_TX_STAT2_REG 0x99 73 + #define MHL_TX_MHLTX_CTL1_REG 0xA0 74 + #define MHL_TX_MHLTX_CTL2_REG 0xA1 75 + #define MHL_TX_MHLTX_CTL4_REG 0xA3 76 + #define MHL_TX_MHLTX_CTL6_REG 0xA5 77 + #define MHL_TX_MHLTX_CTL7_REG 0xA6 78 + 79 + #define RSEN_STATUS BIT(2) 80 + #define HPD_CHANGE_INT BIT(6) 81 + #define RSEN_CHANGE_INT BIT(5) 82 + #define RGND_READY_INT BIT(6) 83 + #define VBUS_LOW_INT BIT(5) 84 + #define CBUS_LKOUT_INT BIT(4) 85 + #define MHL_DISC_FAIL_INT BIT(3) 86 + #define MHL_EST_INT BIT(2) 87 + #define HPD_CHANGE_INT_MASK BIT(6) 88 + #define RSEN_CHANGE_INT_MASK BIT(5) 89 + 90 + #define RGND_READY_MASK BIT(6) 91 + #define CBUS_LKOUT_MASK BIT(4) 92 + #define MHL_DISC_FAIL_MASK BIT(3) 93 + #define MHL_EST_MASK BIT(2) 94 + 95 + #define SKIP_GND BIT(6) 96 + 97 + #define ATT_THRESH_SHIFT 0x04 98 + #define ATT_THRESH_MASK (0x03 << ATT_THRESH_SHIFT) 99 + #define USB_D_OEN BIT(3) 100 + #define DEGLITCH_TIME_MASK 0x07 101 + #define DEGLITCH_TIME_2MS 0 102 + #define DEGLITCH_TIME_4MS 1 103 + #define DEGLITCH_TIME_8MS 2 104 + #define DEGLITCH_TIME_16MS 3 105 + #define DEGLITCH_TIME_40MS 4 106 + #define DEGLITCH_TIME_50MS 5 107 + #define DEGLITCH_TIME_60MS 6 108 + #define DEGLITCH_TIME_128MS 7 109 + 110 + #define USB_D_OVR BIT(7) 111 + #define USB_ID_OVR BIT(6) 112 + #define DVRFLT_SEL BIT(5) 113 + #define BLOCK_RGND_INT BIT(4) 114 + #define SKIP_DEG BIT(3) 115 + #define CI2CA_POL BIT(2) 116 + #define CI2CA_WKUP BIT(1) 117 + #define SINGLE_ATT BIT(0) 118 + 119 + #define USB_D_ODN BIT(5) 120 + #define VBUS_CHECK BIT(2) 121 + #define RGND_INTP_MASK 0x03 122 + #define RGND_INTP_OPEN 0 123 + #define RGND_INTP_2K 1 124 + #define RGND_INTP_1K 2 125 + #define RGND_INTP_SHORT 3 126 + 127 + /* HDMI registers */ 128 + #define HDMI_RX_TMDS0_CCTRL1_REG 0x10 129 + #define HDMI_RX_TMDS_CLK_EN_REG 0x11 130 + #define HDMI_RX_TMDS_CH_EN_REG 0x12 131 + #define HDMI_RX_PLL_CALREFSEL_REG 0x17 132 + #define HDMI_RX_PLL_VCOCAL_REG 0x1A 133 + #define HDMI_RX_EQ_DATA0_REG 0x22 134 + #define HDMI_RX_EQ_DATA1_REG 0x23 135 + #define HDMI_RX_EQ_DATA2_REG 0x24 136 + #define HDMI_RX_EQ_DATA3_REG 0x25 137 + #define HDMI_RX_EQ_DATA4_REG 0x26 138 + #define HDMI_RX_TMDS_ZONE_CTRL_REG 0x4C 139 + #define HDMI_RX_TMDS_MODE_CTRL_REG 0x4D 140 + 141 + /* CBUS registers */ 142 + #define CBUS_INT_STATUS_1_REG 0x08 143 + #define CBUS_INTR1_ENABLE_REG 0x09 144 + #define CBUS_MSC_REQ_ABORT_REASON_REG 0x0D 145 + #define CBUS_INT_STATUS_2_REG 0x1E 146 + #define CBUS_INTR2_ENABLE_REG 0x1F 147 + #define CBUS_LINK_CONTROL_2_REG 0x31 148 + #define CBUS_MHL_STATUS_REG_0 0xB0 149 + #define CBUS_MHL_STATUS_REG_1 0xB1 150 + 151 + #define BIT_CBUS_RESET BIT(3) 152 + #define SET_HPD_DOWNSTREAM BIT(6) 153 + 154 + /* TPI registers */ 155 + #define TPI_DPD_REG 0x3D 156 + 157 + /* Timeouts in msec */ 158 + #define T_SRC_VBUS_CBUS_TO_STABLE 200 159 + #define T_SRC_CBUS_FLOAT 100 160 + #define T_SRC_CBUS_DEGLITCH 2 161 + #define T_SRC_RXSENSE_DEGLITCH 110 162 + 163 + #define MHL1_MAX_CLK 75000 /* in kHz */ 164 + 165 + #define I2C_TPI_ADDR 0x3D 166 + #define I2C_HDMI_ADDR 0x49 167 + #define I2C_CBUS_ADDR 0x64 168 + 169 + enum sii9234_state { 170 + ST_OFF, 171 + ST_D3, 172 + ST_RGND_INIT, 173 + ST_RGND_1K, 174 + ST_RSEN_HIGH, 175 + ST_MHL_ESTABLISHED, 176 + ST_FAILURE_DISCOVERY, 177 + ST_FAILURE, 178 + }; 179 + 180 + struct sii9234 { 181 + struct i2c_client *client[4]; 182 + struct drm_bridge bridge; 183 + struct device *dev; 184 + struct gpio_desc *gpio_reset; 185 + int i2c_error; 186 + struct regulator_bulk_data supplies[4]; 187 + 188 + struct mutex lock; /* Protects fields below and device registers */ 189 + enum sii9234_state state; 190 + }; 191 + 192 + enum sii9234_client_id { 193 + I2C_MHL, 194 + I2C_TPI, 195 + I2C_HDMI, 196 + I2C_CBUS, 197 + }; 198 + 199 + static const char * const sii9234_client_name[] = { 200 + [I2C_MHL] = "MHL", 201 + [I2C_TPI] = "TPI", 202 + [I2C_HDMI] = "HDMI", 203 + [I2C_CBUS] = "CBUS", 204 + }; 205 + 206 + static int sii9234_writeb(struct sii9234 *ctx, int id, int offset, 207 + int value) 208 + { 209 + int ret; 210 + struct i2c_client *client = ctx->client[id]; 211 + 212 + if (ctx->i2c_error) 213 + return ctx->i2c_error; 214 + 215 + ret = i2c_smbus_write_byte_data(client, offset, value); 216 + if (ret < 0) 217 + dev_err(ctx->dev, "writeb: %4s[0x%02x] <- 0x%02x\n", 218 + sii9234_client_name[id], offset, value); 219 + ctx->i2c_error = ret; 220 + 221 + return ret; 222 + } 223 + 224 + static int sii9234_writebm(struct sii9234 *ctx, int id, int offset, 225 + int value, int mask) 226 + { 227 + int ret; 228 + struct i2c_client *client = ctx->client[id]; 229 + 230 + if (ctx->i2c_error) 231 + return ctx->i2c_error; 232 + 233 + ret = i2c_smbus_write_byte(client, offset); 234 + if (ret < 0) { 235 + dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n", 236 + sii9234_client_name[id], offset, value); 237 + ctx->i2c_error = ret; 238 + return ret; 239 + } 240 + 241 + ret = i2c_smbus_read_byte(client); 242 + if (ret < 0) { 243 + dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n", 244 + sii9234_client_name[id], offset, value); 245 + ctx->i2c_error = ret; 246 + return ret; 247 + } 248 + 249 + value = (value & mask) | (ret & ~mask); 250 + 251 + ret = i2c_smbus_write_byte_data(client, offset, value); 252 + if (ret < 0) { 253 + dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n", 254 + sii9234_client_name[id], offset, value); 255 + ctx->i2c_error = ret; 256 + } 257 + 258 + return ret; 259 + } 260 + 261 + static int sii9234_readb(struct sii9234 *ctx, int id, int offset) 262 + { 263 + int ret; 264 + struct i2c_client *client = ctx->client[id]; 265 + 266 + if (ctx->i2c_error) 267 + return ctx->i2c_error; 268 + 269 + ret = i2c_smbus_write_byte(client, offset); 270 + if (ret < 0) { 271 + dev_err(ctx->dev, "readb: %4s[0x%02x]\n", 272 + sii9234_client_name[id], offset); 273 + ctx->i2c_error = ret; 274 + return ret; 275 + } 276 + 277 + ret = i2c_smbus_read_byte(client); 278 + if (ret < 0) { 279 + dev_err(ctx->dev, "readb: %4s[0x%02x]\n", 280 + sii9234_client_name[id], offset); 281 + ctx->i2c_error = ret; 282 + } 283 + 284 + return ret; 285 + } 286 + 287 + static int sii9234_clear_error(struct sii9234 *ctx) 288 + { 289 + int ret = ctx->i2c_error; 290 + 291 + ctx->i2c_error = 0; 292 + 293 + return ret; 294 + } 295 + 296 + #define mhl_tx_writeb(sii9234, offset, value) \ 297 + sii9234_writeb(sii9234, I2C_MHL, offset, value) 298 + #define mhl_tx_writebm(sii9234, offset, value, mask) \ 299 + sii9234_writebm(sii9234, I2C_MHL, offset, value, mask) 300 + #define mhl_tx_readb(sii9234, offset) \ 301 + sii9234_readb(sii9234, I2C_MHL, offset) 302 + #define cbus_writeb(sii9234, offset, value) \ 303 + sii9234_writeb(sii9234, I2C_CBUS, offset, value) 304 + #define cbus_writebm(sii9234, offset, value, mask) \ 305 + sii9234_writebm(sii9234, I2C_CBUS, offset, value, mask) 306 + #define cbus_readb(sii9234, offset) \ 307 + sii9234_readb(sii9234, I2C_CBUS, offset) 308 + #define hdmi_writeb(sii9234, offset, value) \ 309 + sii9234_writeb(sii9234, I2C_HDMI, offset, value) 310 + #define hdmi_writebm(sii9234, offset, value, mask) \ 311 + sii9234_writebm(sii9234, I2C_HDMI, offset, value, mask) 312 + #define hdmi_readb(sii9234, offset) \ 313 + sii9234_readb(sii9234, I2C_HDMI, offset) 314 + #define tpi_writeb(sii9234, offset, value) \ 315 + sii9234_writeb(sii9234, I2C_TPI, offset, value) 316 + #define tpi_writebm(sii9234, offset, value, mask) \ 317 + sii9234_writebm(sii9234, I2C_TPI, offset, value, mask) 318 + #define tpi_readb(sii9234, offset) \ 319 + sii9234_readb(sii9234, I2C_TPI, offset) 320 + 321 + static u8 sii9234_tmds_control(struct sii9234 *ctx, bool enable) 322 + { 323 + mhl_tx_writebm(ctx, MHL_TX_TMDS_CCTRL, enable ? ~0 : 0, 324 + BIT_TMDS_CCTRL_TMDS_OE); 325 + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, enable ? ~0 : 0, 326 + MHL_HPD_OUT_OVR_EN | MHL_HPD_OUT_OVR_VAL); 327 + return sii9234_clear_error(ctx); 328 + } 329 + 330 + static int sii9234_cbus_reset(struct sii9234 *ctx) 331 + { 332 + int i; 333 + 334 + mhl_tx_writebm(ctx, MHL_TX_SRST, ~0, BIT_CBUS_RESET); 335 + msleep(T_SRC_CBUS_DEGLITCH); 336 + mhl_tx_writebm(ctx, MHL_TX_SRST, 0, BIT_CBUS_RESET); 337 + 338 + for (i = 0; i < 4; i++) { 339 + /* 340 + * Enable WRITE_STAT interrupt for writes to all 341 + * 4 MSC Status registers. 342 + */ 343 + cbus_writeb(ctx, 0xE0 + i, 0xF2); 344 + /* 345 + * Enable SET_INT interrupt for writes to all 346 + * 4 MSC Interrupt registers. 347 + */ 348 + cbus_writeb(ctx, 0xF0 + i, 0xF2); 349 + } 350 + 351 + return sii9234_clear_error(ctx); 352 + } 353 + 354 + /* Require to chek mhl imformation of samsung in cbus_init_register */ 355 + static int sii9234_cbus_init(struct sii9234 *ctx) 356 + { 357 + cbus_writeb(ctx, 0x07, 0xF2); 358 + cbus_writeb(ctx, 0x40, 0x03); 359 + cbus_writeb(ctx, 0x42, 0x06); 360 + cbus_writeb(ctx, 0x36, 0x0C); 361 + cbus_writeb(ctx, 0x3D, 0xFD); 362 + cbus_writeb(ctx, 0x1C, 0x01); 363 + cbus_writeb(ctx, 0x1D, 0x0F); 364 + cbus_writeb(ctx, 0x44, 0x02); 365 + /* Setup our devcap */ 366 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEV_STATE, 0x00); 367 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_MHL_VERSION, 368 + SII9234_MHL_VERSION); 369 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_CAT, 370 + MHL_DCAP_CAT_SOURCE); 371 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_ADOPTER_ID_H, 0x01); 372 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_ADOPTER_ID_L, 0x41); 373 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_VID_LINK_MODE, 374 + MHL_DCAP_VID_LINK_RGB444 | MHL_DCAP_VID_LINK_YCBCR444); 375 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_VIDEO_TYPE, 376 + MHL_DCAP_VT_GRAPHICS); 377 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_LOG_DEV_MAP, 378 + MHL_DCAP_LD_GUI); 379 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_BANDWIDTH, 0x0F); 380 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_FEATURE_FLAG, 381 + MHL_DCAP_FEATURE_RCP_SUPPORT | MHL_DCAP_FEATURE_RAP_SUPPORT 382 + | MHL_DCAP_FEATURE_SP_SUPPORT); 383 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEVICE_ID_H, 0x0); 384 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEVICE_ID_L, 0x0); 385 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_SCRATCHPAD_SIZE, 386 + SII9234_SCRATCHPAD_SIZE); 387 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_INT_STAT_SIZE, 388 + SII9234_INT_STAT_SIZE); 389 + cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_RESERVED, 0); 390 + cbus_writebm(ctx, 0x31, 0x0C, 0x0C); 391 + cbus_writeb(ctx, 0x30, 0x01); 392 + cbus_writebm(ctx, 0x3C, 0x30, 0x38); 393 + cbus_writebm(ctx, 0x22, 0x0D, 0x0F); 394 + cbus_writebm(ctx, 0x2E, 0x15, 0x15); 395 + cbus_writeb(ctx, CBUS_INTR1_ENABLE_REG, 0); 396 + cbus_writeb(ctx, CBUS_INTR2_ENABLE_REG, 0); 397 + 398 + return sii9234_clear_error(ctx); 399 + } 400 + 401 + static void force_usb_id_switch_open(struct sii9234 *ctx) 402 + { 403 + /* Disable CBUS discovery */ 404 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, 0, 0x01); 405 + /* Force USB ID switch to open */ 406 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, USB_ID_OVR); 407 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL3_REG, ~0, 0x86); 408 + /* Force upstream HPD to 0 when not in MHL mode. */ 409 + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 0x30); 410 + } 411 + 412 + static void release_usb_id_switch_open(struct sii9234 *ctx) 413 + { 414 + msleep(T_SRC_CBUS_FLOAT); 415 + /* Clear USB ID switch to open */ 416 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, 0, USB_ID_OVR); 417 + /* Enable CBUS discovery */ 418 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, ~0, 0x01); 419 + } 420 + 421 + static int sii9234_power_init(struct sii9234 *ctx) 422 + { 423 + /* Force the SiI9234 into the D0 state. */ 424 + tpi_writeb(ctx, TPI_DPD_REG, 0x3F); 425 + /* Enable TxPLL Clock */ 426 + hdmi_writeb(ctx, HDMI_RX_TMDS_CLK_EN_REG, 0x01); 427 + /* Enable Tx Clock Path & Equalizer */ 428 + hdmi_writeb(ctx, HDMI_RX_TMDS_CH_EN_REG, 0x15); 429 + /* Power Up TMDS */ 430 + mhl_tx_writeb(ctx, 0x08, 0x35); 431 + return sii9234_clear_error(ctx); 432 + } 433 + 434 + static int sii9234_hdmi_init(struct sii9234 *ctx) 435 + { 436 + hdmi_writeb(ctx, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1); 437 + hdmi_writeb(ctx, HDMI_RX_PLL_CALREFSEL_REG, 0x03); 438 + hdmi_writeb(ctx, HDMI_RX_PLL_VCOCAL_REG, 0x20); 439 + hdmi_writeb(ctx, HDMI_RX_EQ_DATA0_REG, 0x8A); 440 + hdmi_writeb(ctx, HDMI_RX_EQ_DATA1_REG, 0x6A); 441 + hdmi_writeb(ctx, HDMI_RX_EQ_DATA2_REG, 0xAA); 442 + hdmi_writeb(ctx, HDMI_RX_EQ_DATA3_REG, 0xCA); 443 + hdmi_writeb(ctx, HDMI_RX_EQ_DATA4_REG, 0xEA); 444 + hdmi_writeb(ctx, HDMI_RX_TMDS_ZONE_CTRL_REG, 0xA0); 445 + hdmi_writeb(ctx, HDMI_RX_TMDS_MODE_CTRL_REG, 0x00); 446 + mhl_tx_writeb(ctx, MHL_TX_TMDS_CCTRL, 0x34); 447 + hdmi_writeb(ctx, 0x45, 0x44); 448 + hdmi_writeb(ctx, 0x31, 0x0A); 449 + hdmi_writeb(ctx, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1); 450 + 451 + return sii9234_clear_error(ctx); 452 + } 453 + 454 + static int sii9234_mhl_tx_ctl_int(struct sii9234 *ctx) 455 + { 456 + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL1_REG, 0xD0); 457 + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL2_REG, 0xFC); 458 + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL4_REG, 0xEB); 459 + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL7_REG, 0x0C); 460 + 461 + return sii9234_clear_error(ctx); 462 + } 463 + 464 + static int sii9234_reset(struct sii9234 *ctx) 465 + { 466 + int ret; 467 + 468 + sii9234_clear_error(ctx); 469 + 470 + ret = sii9234_power_init(ctx); 471 + if (ret < 0) 472 + return ret; 473 + ret = sii9234_cbus_reset(ctx); 474 + if (ret < 0) 475 + return ret; 476 + ret = sii9234_hdmi_init(ctx); 477 + if (ret < 0) 478 + return ret; 479 + ret = sii9234_mhl_tx_ctl_int(ctx); 480 + if (ret < 0) 481 + return ret; 482 + 483 + /* Enable HDCP Compliance safety */ 484 + mhl_tx_writeb(ctx, 0x2B, 0x01); 485 + /* CBUS discovery cycle time for each drive and float = 150us */ 486 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, 0x04, 0x06); 487 + /* Clear bit 6 (reg_skip_rgnd) */ 488 + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL2_REG, (1 << 7) /* Reserved */ 489 + | 2 << ATT_THRESH_SHIFT | DEGLITCH_TIME_50MS); 490 + /* 491 + * Changed from 66 to 65 for 94[1:0] = 01 = 5k reg_cbusmhl_pup_sel 492 + * 1.8V CBUS VTH & GND threshold 493 + * to meet CTS 3.3.7.2 spec 494 + */ 495 + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL5_REG, 0x77); 496 + cbus_writebm(ctx, CBUS_LINK_CONTROL_2_REG, ~0, MHL_INIT_TIMEOUT); 497 + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL6_REG, 0xA0); 498 + /* RGND & single discovery attempt (RGND blocking) */ 499 + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL6_REG, BLOCK_RGND_INT | 500 + DVRFLT_SEL | SINGLE_ATT); 501 + /* Use VBUS path of discovery state machine */ 502 + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL8_REG, 0); 503 + /* 0x92[3] sets the CBUS / ID switch */ 504 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, USB_ID_OVR); 505 + /* 506 + * To allow RGND engine to operate correctly. 507 + * When moving the chip from D2 to D0 (power up, init regs) 508 + * the values should be 509 + * 94[1:0] = 01 reg_cbusmhl_pup_sel[1:0] should be set for 5k 510 + * 93[7:6] = 10 reg_cbusdisc_pup_sel[1:0] should be 511 + * set for 10k (default) 512 + * 93[5:4] = 00 reg_cbusidle_pup_sel[1:0] = open (default) 513 + */ 514 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL3_REG, ~0, 0x86); 515 + /* 516 + * Change from CC to 8C to match 5K 517 + * to meet CTS 3.3.72 spec 518 + */ 519 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, ~0, 0x8C); 520 + /* Configure the interrupt as active high */ 521 + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 0x06); 522 + 523 + msleep(25); 524 + 525 + /* Release usb_id switch */ 526 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, 0, USB_ID_OVR); 527 + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL1_REG, 0x27); 528 + 529 + ret = sii9234_clear_error(ctx); 530 + if (ret < 0) 531 + return ret; 532 + ret = sii9234_cbus_init(ctx); 533 + if (ret < 0) 534 + return ret; 535 + 536 + /* Enable Auto soft reset on SCDT = 0 */ 537 + mhl_tx_writeb(ctx, 0x05, 0x04); 538 + /* HDMI Transcode mode enable */ 539 + mhl_tx_writeb(ctx, 0x0D, 0x1C); 540 + mhl_tx_writeb(ctx, MHL_TX_INTR4_ENABLE_REG, 541 + RGND_READY_MASK | CBUS_LKOUT_MASK 542 + | MHL_DISC_FAIL_MASK | MHL_EST_MASK); 543 + mhl_tx_writeb(ctx, MHL_TX_INTR1_ENABLE_REG, 0x60); 544 + 545 + /* This point is very important before measure RGND impedance */ 546 + force_usb_id_switch_open(ctx); 547 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, 0, 0xF0); 548 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL5_REG, 0, 0x03); 549 + release_usb_id_switch_open(ctx); 550 + 551 + /* Force upstream HPD to 0 when not in MHL mode */ 552 + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 1 << 5); 553 + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, ~0, 1 << 4); 554 + 555 + return sii9234_clear_error(ctx); 556 + } 557 + 558 + static int sii9234_goto_d3(struct sii9234 *ctx) 559 + { 560 + int ret; 561 + 562 + dev_dbg(ctx->dev, "sii9234: detection started d3\n"); 563 + 564 + ret = sii9234_reset(ctx); 565 + if (ret < 0) 566 + goto exit; 567 + 568 + hdmi_writeb(ctx, 0x01, 0x03); 569 + tpi_writebm(ctx, TPI_DPD_REG, 0, 1); 570 + /* I2C above is expected to fail because power goes down */ 571 + sii9234_clear_error(ctx); 572 + 573 + ctx->state = ST_D3; 574 + 575 + return 0; 576 + exit: 577 + dev_err(ctx->dev, "%s failed\n", __func__); 578 + return -1; 579 + } 580 + 581 + static int sii9234_hw_on(struct sii9234 *ctx) 582 + { 583 + return regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 584 + } 585 + 586 + static void sii9234_hw_off(struct sii9234 *ctx) 587 + { 588 + gpiod_set_value(ctx->gpio_reset, 1); 589 + msleep(20); 590 + regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 591 + } 592 + 593 + static void sii9234_hw_reset(struct sii9234 *ctx) 594 + { 595 + gpiod_set_value(ctx->gpio_reset, 1); 596 + msleep(20); 597 + gpiod_set_value(ctx->gpio_reset, 0); 598 + } 599 + 600 + static void sii9234_cable_in(struct sii9234 *ctx) 601 + { 602 + int ret; 603 + 604 + mutex_lock(&ctx->lock); 605 + if (ctx->state != ST_OFF) 606 + goto unlock; 607 + ret = sii9234_hw_on(ctx); 608 + if (ret < 0) 609 + goto unlock; 610 + 611 + sii9234_hw_reset(ctx); 612 + sii9234_goto_d3(ctx); 613 + /* To avoid irq storm, when hw is in meta state */ 614 + enable_irq(to_i2c_client(ctx->dev)->irq); 615 + 616 + unlock: 617 + mutex_unlock(&ctx->lock); 618 + } 619 + 620 + static void sii9234_cable_out(struct sii9234 *ctx) 621 + { 622 + mutex_lock(&ctx->lock); 623 + 624 + if (ctx->state == ST_OFF) 625 + goto unlock; 626 + 627 + disable_irq(to_i2c_client(ctx->dev)->irq); 628 + tpi_writeb(ctx, TPI_DPD_REG, 0); 629 + /* Turn on&off hpd festure for only QCT HDMI */ 630 + sii9234_hw_off(ctx); 631 + 632 + ctx->state = ST_OFF; 633 + 634 + unlock: 635 + mutex_unlock(&ctx->lock); 636 + } 637 + 638 + static enum sii9234_state sii9234_rgnd_ready_irq(struct sii9234 *ctx) 639 + { 640 + int value; 641 + 642 + if (ctx->state == ST_D3) { 643 + int ret; 644 + 645 + dev_dbg(ctx->dev, "RGND_READY_INT\n"); 646 + sii9234_hw_reset(ctx); 647 + 648 + ret = sii9234_reset(ctx); 649 + if (ret < 0) { 650 + dev_err(ctx->dev, "sii9234_reset() failed\n"); 651 + return ST_FAILURE; 652 + } 653 + 654 + return ST_RGND_INIT; 655 + } 656 + 657 + /* Got interrupt in inappropriate state */ 658 + if (ctx->state != ST_RGND_INIT) 659 + return ST_FAILURE; 660 + 661 + value = mhl_tx_readb(ctx, MHL_TX_STAT2_REG); 662 + if (sii9234_clear_error(ctx)) 663 + return ST_FAILURE; 664 + 665 + if ((value & RGND_INTP_MASK) != RGND_INTP_1K) { 666 + dev_warn(ctx->dev, "RGND is not 1k\n"); 667 + return ST_RGND_INIT; 668 + } 669 + dev_dbg(ctx->dev, "RGND 1K!!\n"); 670 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, ~0, 0x8C); 671 + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL5_REG, 0x77); 672 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, 0x05); 673 + if (sii9234_clear_error(ctx)) 674 + return ST_FAILURE; 675 + 676 + msleep(T_SRC_VBUS_CBUS_TO_STABLE); 677 + return ST_RGND_1K; 678 + } 679 + 680 + static enum sii9234_state sii9234_mhl_established(struct sii9234 *ctx) 681 + { 682 + dev_dbg(ctx->dev, "mhl est interrupt\n"); 683 + 684 + /* Discovery override */ 685 + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL1_REG, 0x10); 686 + /* Increase DDC translation layer timer (byte mode) */ 687 + cbus_writeb(ctx, 0x07, 0x32); 688 + cbus_writebm(ctx, 0x44, ~0, 1 << 1); 689 + /* Keep the discovery enabled. Need RGND interrupt */ 690 + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, ~0, 1); 691 + mhl_tx_writeb(ctx, MHL_TX_INTR1_ENABLE_REG, 692 + RSEN_CHANGE_INT_MASK | HPD_CHANGE_INT_MASK); 693 + 694 + if (sii9234_clear_error(ctx)) 695 + return ST_FAILURE; 696 + 697 + return ST_MHL_ESTABLISHED; 698 + } 699 + 700 + static enum sii9234_state sii9234_hpd_change(struct sii9234 *ctx) 701 + { 702 + int value; 703 + 704 + value = cbus_readb(ctx, CBUS_MSC_REQ_ABORT_REASON_REG); 705 + if (sii9234_clear_error(ctx)) 706 + return ST_FAILURE; 707 + 708 + if (value & SET_HPD_DOWNSTREAM) { 709 + /* Downstream HPD High, Enable TMDS */ 710 + sii9234_tmds_control(ctx, true); 711 + } else { 712 + /* Downstream HPD Low, Disable TMDS */ 713 + sii9234_tmds_control(ctx, false); 714 + } 715 + 716 + return ctx->state; 717 + } 718 + 719 + static enum sii9234_state sii9234_rsen_change(struct sii9234 *ctx) 720 + { 721 + int value; 722 + 723 + /* Work_around code to handle wrong interrupt */ 724 + if (ctx->state != ST_RGND_1K) { 725 + dev_err(ctx->dev, "RSEN_HIGH without RGND_1K\n"); 726 + return ST_FAILURE; 727 + } 728 + value = mhl_tx_readb(ctx, MHL_TX_SYSSTAT_REG); 729 + if (value < 0) 730 + return ST_FAILURE; 731 + 732 + if (value & RSEN_STATUS) { 733 + dev_dbg(ctx->dev, "MHL cable connected.. RSEN High\n"); 734 + return ST_RSEN_HIGH; 735 + } 736 + dev_dbg(ctx->dev, "RSEN lost\n"); 737 + /* 738 + * Once RSEN loss is confirmed,we need to check 739 + * based on cable status and chip power status,whether 740 + * it is SINK Loss(HDMI cable not connected, TV Off) 741 + * or MHL cable disconnection 742 + * TODO: Define the below mhl_disconnection() 743 + */ 744 + msleep(T_SRC_RXSENSE_DEGLITCH); 745 + value = mhl_tx_readb(ctx, MHL_TX_SYSSTAT_REG); 746 + if (value < 0) 747 + return ST_FAILURE; 748 + dev_dbg(ctx->dev, "sys_stat: %x\n", value); 749 + 750 + if (value & RSEN_STATUS) { 751 + dev_dbg(ctx->dev, "RSEN recovery\n"); 752 + return ST_RSEN_HIGH; 753 + } 754 + dev_dbg(ctx->dev, "RSEN Really LOW\n"); 755 + /* To meet CTS 3.3.22.2 spec */ 756 + sii9234_tmds_control(ctx, false); 757 + force_usb_id_switch_open(ctx); 758 + release_usb_id_switch_open(ctx); 759 + 760 + return ST_FAILURE; 761 + } 762 + 763 + static irqreturn_t sii9234_irq_thread(int irq, void *data) 764 + { 765 + struct sii9234 *ctx = data; 766 + int intr1, intr4; 767 + int intr1_en, intr4_en; 768 + int cbus_intr1, cbus_intr2; 769 + 770 + dev_dbg(ctx->dev, "%s\n", __func__); 771 + 772 + mutex_lock(&ctx->lock); 773 + 774 + intr1 = mhl_tx_readb(ctx, MHL_TX_INTR1_REG); 775 + intr4 = mhl_tx_readb(ctx, MHL_TX_INTR4_REG); 776 + intr1_en = mhl_tx_readb(ctx, MHL_TX_INTR1_ENABLE_REG); 777 + intr4_en = mhl_tx_readb(ctx, MHL_TX_INTR4_ENABLE_REG); 778 + cbus_intr1 = cbus_readb(ctx, CBUS_INT_STATUS_1_REG); 779 + cbus_intr2 = cbus_readb(ctx, CBUS_INT_STATUS_2_REG); 780 + 781 + if (sii9234_clear_error(ctx)) 782 + goto done; 783 + 784 + dev_dbg(ctx->dev, "irq %02x/%02x %02x/%02x %02x/%02x\n", 785 + intr1, intr1_en, intr4, intr4_en, cbus_intr1, cbus_intr2); 786 + 787 + if (intr4 & RGND_READY_INT) 788 + ctx->state = sii9234_rgnd_ready_irq(ctx); 789 + if (intr1 & RSEN_CHANGE_INT) 790 + ctx->state = sii9234_rsen_change(ctx); 791 + if (intr4 & MHL_EST_INT) 792 + ctx->state = sii9234_mhl_established(ctx); 793 + if (intr1 & HPD_CHANGE_INT) 794 + ctx->state = sii9234_hpd_change(ctx); 795 + if (intr4 & CBUS_LKOUT_INT) 796 + ctx->state = ST_FAILURE; 797 + if (intr4 & MHL_DISC_FAIL_INT) 798 + ctx->state = ST_FAILURE_DISCOVERY; 799 + 800 + done: 801 + /* Clean interrupt status and pending flags */ 802 + mhl_tx_writeb(ctx, MHL_TX_INTR1_REG, intr1); 803 + mhl_tx_writeb(ctx, MHL_TX_INTR4_REG, intr4); 804 + cbus_writeb(ctx, CBUS_MHL_STATUS_REG_0, 0xFF); 805 + cbus_writeb(ctx, CBUS_MHL_STATUS_REG_1, 0xFF); 806 + cbus_writeb(ctx, CBUS_INT_STATUS_1_REG, cbus_intr1); 807 + cbus_writeb(ctx, CBUS_INT_STATUS_2_REG, cbus_intr2); 808 + 809 + sii9234_clear_error(ctx); 810 + 811 + if (ctx->state == ST_FAILURE) { 812 + dev_dbg(ctx->dev, "try to reset after failure\n"); 813 + sii9234_hw_reset(ctx); 814 + sii9234_goto_d3(ctx); 815 + } 816 + 817 + if (ctx->state == ST_FAILURE_DISCOVERY) { 818 + dev_err(ctx->dev, "discovery failed, no power for MHL?\n"); 819 + tpi_writebm(ctx, TPI_DPD_REG, 0, 1); 820 + ctx->state = ST_D3; 821 + } 822 + 823 + mutex_unlock(&ctx->lock); 824 + 825 + return IRQ_HANDLED; 826 + } 827 + 828 + static int sii9234_init_resources(struct sii9234 *ctx, 829 + struct i2c_client *client) 830 + { 831 + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 832 + int ret; 833 + 834 + if (!ctx->dev->of_node) { 835 + dev_err(ctx->dev, "not DT device\n"); 836 + return -ENODEV; 837 + } 838 + 839 + ctx->gpio_reset = devm_gpiod_get(ctx->dev, "reset", GPIOD_OUT_LOW); 840 + if (IS_ERR(ctx->gpio_reset)) { 841 + dev_err(ctx->dev, "failed to get reset gpio from DT\n"); 842 + return PTR_ERR(ctx->gpio_reset); 843 + } 844 + 845 + ctx->supplies[0].supply = "avcc12"; 846 + ctx->supplies[1].supply = "avcc33"; 847 + ctx->supplies[2].supply = "iovcc18"; 848 + ctx->supplies[3].supply = "cvcc12"; 849 + ret = devm_regulator_bulk_get(ctx->dev, 4, ctx->supplies); 850 + if (ret) { 851 + dev_err(ctx->dev, "regulator_bulk failed\n"); 852 + return ret; 853 + } 854 + 855 + ctx->client[I2C_MHL] = client; 856 + 857 + ctx->client[I2C_TPI] = i2c_new_dummy(adapter, I2C_TPI_ADDR); 858 + if (!ctx->client[I2C_TPI]) { 859 + dev_err(ctx->dev, "failed to create TPI client\n"); 860 + return -ENODEV; 861 + } 862 + 863 + ctx->client[I2C_HDMI] = i2c_new_dummy(adapter, I2C_HDMI_ADDR); 864 + if (!ctx->client[I2C_HDMI]) { 865 + dev_err(ctx->dev, "failed to create HDMI RX client\n"); 866 + goto fail_tpi; 867 + } 868 + 869 + ctx->client[I2C_CBUS] = i2c_new_dummy(adapter, I2C_CBUS_ADDR); 870 + if (!ctx->client[I2C_CBUS]) { 871 + dev_err(ctx->dev, "failed to create CBUS client\n"); 872 + goto fail_hdmi; 873 + } 874 + 875 + return 0; 876 + 877 + fail_hdmi: 878 + i2c_unregister_device(ctx->client[I2C_HDMI]); 879 + fail_tpi: 880 + i2c_unregister_device(ctx->client[I2C_TPI]); 881 + 882 + return -ENODEV; 883 + } 884 + 885 + static void sii9234_deinit_resources(struct sii9234 *ctx) 886 + { 887 + i2c_unregister_device(ctx->client[I2C_CBUS]); 888 + i2c_unregister_device(ctx->client[I2C_HDMI]); 889 + i2c_unregister_device(ctx->client[I2C_TPI]); 890 + } 891 + 892 + static inline struct sii9234 *bridge_to_sii9234(struct drm_bridge *bridge) 893 + { 894 + return container_of(bridge, struct sii9234, bridge); 895 + } 896 + 897 + static enum drm_mode_status sii9234_mode_valid(struct drm_bridge *bridge, 898 + const struct drm_display_mode *mode) 899 + { 900 + if (mode->clock > MHL1_MAX_CLK) 901 + return MODE_CLOCK_HIGH; 902 + 903 + return MODE_OK; 904 + } 905 + 906 + static const struct drm_bridge_funcs sii9234_bridge_funcs = { 907 + .mode_valid = sii9234_mode_valid, 908 + }; 909 + 910 + static int sii9234_probe(struct i2c_client *client, 911 + const struct i2c_device_id *id) 912 + { 913 + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 914 + struct sii9234 *ctx; 915 + struct device *dev = &client->dev; 916 + int ret; 917 + 918 + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 919 + if (!ctx) 920 + return -ENOMEM; 921 + 922 + ctx->dev = dev; 923 + mutex_init(&ctx->lock); 924 + 925 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 926 + dev_err(dev, "I2C adapter lacks SMBUS feature\n"); 927 + return -EIO; 928 + } 929 + 930 + if (!client->irq) { 931 + dev_err(dev, "no irq provided\n"); 932 + return -EINVAL; 933 + } 934 + 935 + irq_set_status_flags(client->irq, IRQ_NOAUTOEN); 936 + ret = devm_request_threaded_irq(dev, client->irq, NULL, 937 + sii9234_irq_thread, 938 + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 939 + "sii9234", ctx); 940 + if (ret < 0) { 941 + dev_err(dev, "failed to install IRQ handler\n"); 942 + return ret; 943 + } 944 + 945 + ret = sii9234_init_resources(ctx, client); 946 + if (ret < 0) 947 + return ret; 948 + 949 + i2c_set_clientdata(client, ctx); 950 + 951 + ctx->bridge.funcs = &sii9234_bridge_funcs; 952 + ctx->bridge.of_node = dev->of_node; 953 + drm_bridge_add(&ctx->bridge); 954 + 955 + sii9234_cable_in(ctx); 956 + 957 + return 0; 958 + } 959 + 960 + static int sii9234_remove(struct i2c_client *client) 961 + { 962 + struct sii9234 *ctx = i2c_get_clientdata(client); 963 + 964 + sii9234_cable_out(ctx); 965 + drm_bridge_remove(&ctx->bridge); 966 + sii9234_deinit_resources(ctx); 967 + 968 + return 0; 969 + } 970 + 971 + static const struct of_device_id sii9234_dt_match[] = { 972 + { .compatible = "sil,sii9234" }, 973 + { }, 974 + }; 975 + MODULE_DEVICE_TABLE(of, sii9234_dt_match); 976 + 977 + static const struct i2c_device_id sii9234_id[] = { 978 + { "SII9234", 0 }, 979 + { }, 980 + }; 981 + MODULE_DEVICE_TABLE(i2c, sii9234_id); 982 + 983 + static struct i2c_driver sii9234_driver = { 984 + .driver = { 985 + .name = "sii9234", 986 + .of_match_table = sii9234_dt_match, 987 + }, 988 + .probe = sii9234_probe, 989 + .remove = sii9234_remove, 990 + .id_table = sii9234_id, 991 + }; 992 + 993 + module_i2c_driver(sii9234_driver); 994 + MODULE_LICENSE("GPL");
+91 -5
drivers/gpu/drm/bridge/sil-sii8620.c
··· 28 28 #include <linux/regulator/consumer.h> 29 29 #include <linux/slab.h> 30 30 31 + #include <media/rc-core.h> 32 + 31 33 #include "sil-sii8620.h" 32 34 33 35 #define SII8620_BURST_BUF_LEN 288 ··· 60 58 struct sii8620 { 61 59 struct drm_bridge bridge; 62 60 struct device *dev; 61 + struct rc_dev *rc_dev; 63 62 struct clk *clk_xtal; 64 63 struct gpio_desc *gpio_reset; 65 64 struct gpio_desc *gpio_int; ··· 432 429 static void sii8620_mt_rap(struct sii8620 *ctx, u8 code) 433 430 { 434 431 sii8620_mt_msc_msg(ctx, MHL_MSC_MSG_RAP, code); 432 + } 433 + 434 + static void sii8620_mt_rcpk(struct sii8620 *ctx, u8 code) 435 + { 436 + sii8620_mt_msc_msg(ctx, MHL_MSC_MSG_RCPK, code); 437 + } 438 + 439 + static void sii8620_mt_rcpe(struct sii8620 *ctx, u8 code) 440 + { 441 + sii8620_mt_msc_msg(ctx, MHL_MSC_MSG_RCPE, code); 435 442 } 436 443 437 444 static void sii8620_mt_read_devcap_send(struct sii8620 *ctx, ··· 1766 1753 sii8620_write_buf(ctx, REG_MDT_XMIT_WRITE_PORT, buf, ARRAY_SIZE(buf)); 1767 1754 } 1768 1755 1756 + static bool sii8620_rcp_consume(struct sii8620 *ctx, u8 scancode) 1757 + { 1758 + bool pressed = !(scancode & MHL_RCP_KEY_RELEASED_MASK); 1759 + 1760 + scancode &= MHL_RCP_KEY_ID_MASK; 1761 + 1762 + if (!ctx->rc_dev) { 1763 + dev_dbg(ctx->dev, "RCP input device not initialized\n"); 1764 + return false; 1765 + } 1766 + 1767 + if (pressed) 1768 + rc_keydown(ctx->rc_dev, RC_PROTO_CEC, scancode, 0); 1769 + else 1770 + rc_keyup(ctx->rc_dev); 1771 + 1772 + return true; 1773 + } 1774 + 1769 1775 static void sii8620_msc_mr_set_int(struct sii8620 *ctx) 1770 1776 { 1771 1777 u8 ints[MHL_INT_SIZE]; ··· 1836 1804 1837 1805 static void sii8620_msc_mr_msc_msg(struct sii8620 *ctx) 1838 1806 { 1839 - struct sii8620_mt_msg *msg = sii8620_msc_msg_first(ctx); 1807 + struct sii8620_mt_msg *msg; 1840 1808 u8 buf[2]; 1841 - 1842 - if (!msg) 1843 - return; 1844 1809 1845 1810 sii8620_read_buf(ctx, REG_MSC_MR_MSC_MSG_RCVD_1ST_DATA, buf, 2); 1846 1811 1847 1812 switch (buf[0]) { 1848 1813 case MHL_MSC_MSG_RAPK: 1814 + msg = sii8620_msc_msg_first(ctx); 1815 + if (!msg) 1816 + return; 1849 1817 msg->ret = buf[1]; 1850 1818 ctx->mt_state = MT_STATE_DONE; 1819 + break; 1820 + case MHL_MSC_MSG_RCP: 1821 + if (!sii8620_rcp_consume(ctx, buf[1])) 1822 + sii8620_mt_rcpe(ctx, 1823 + MHL_RCPE_STATUS_INEFFECTIVE_KEY_CODE); 1824 + sii8620_mt_rcpk(ctx, buf[1]); 1851 1825 break; 1852 1826 default: 1853 1827 dev_err(ctx->dev, "%s message type %d,%d not supported", ··· 2140 2102 enable_irq(to_i2c_client(ctx->dev)->irq); 2141 2103 } 2142 2104 2105 + static void sii8620_init_rcp_input_dev(struct sii8620 *ctx) 2106 + { 2107 + struct rc_dev *rc_dev; 2108 + int ret; 2109 + 2110 + rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE); 2111 + if (!rc_dev) { 2112 + dev_err(ctx->dev, "Failed to allocate RC device\n"); 2113 + ctx->error = -ENOMEM; 2114 + return; 2115 + } 2116 + 2117 + rc_dev->input_phys = "sii8620/input0"; 2118 + rc_dev->input_id.bustype = BUS_VIRTUAL; 2119 + rc_dev->map_name = RC_MAP_CEC; 2120 + rc_dev->allowed_protocols = RC_PROTO_BIT_CEC; 2121 + rc_dev->driver_name = "sii8620"; 2122 + rc_dev->device_name = "sii8620"; 2123 + 2124 + ret = rc_register_device(rc_dev); 2125 + 2126 + if (ret) { 2127 + dev_err(ctx->dev, "Failed to register RC device\n"); 2128 + ctx->error = ret; 2129 + rc_free_device(ctx->rc_dev); 2130 + return; 2131 + } 2132 + ctx->rc_dev = rc_dev; 2133 + } 2134 + 2143 2135 static inline struct sii8620 *bridge_to_sii8620(struct drm_bridge *bridge) 2144 2136 { 2145 2137 return container_of(bridge, struct sii8620, bridge); 2138 + } 2139 + 2140 + static int sii8620_attach(struct drm_bridge *bridge) 2141 + { 2142 + struct sii8620 *ctx = bridge_to_sii8620(bridge); 2143 + 2144 + sii8620_init_rcp_input_dev(ctx); 2145 + 2146 + return sii8620_clear_error(ctx); 2147 + } 2148 + 2149 + static void sii8620_detach(struct drm_bridge *bridge) 2150 + { 2151 + struct sii8620 *ctx = bridge_to_sii8620(bridge); 2152 + 2153 + rc_unregister_device(ctx->rc_dev); 2146 2154 } 2147 2155 2148 2156 static bool sii8620_mode_fixup(struct drm_bridge *bridge, ··· 2235 2151 } 2236 2152 2237 2153 static const struct drm_bridge_funcs sii8620_bridge_funcs = { 2154 + .attach = sii8620_attach, 2155 + .detach = sii8620_detach, 2238 2156 .mode_fixup = sii8620_mode_fixup, 2239 2157 }; 2240 2158 ··· 2303 2217 struct sii8620 *ctx = i2c_get_clientdata(client); 2304 2218 2305 2219 disable_irq(to_i2c_client(ctx->dev)->irq); 2306 - drm_bridge_remove(&ctx->bridge); 2307 2220 sii8620_hw_off(ctx); 2221 + drm_bridge_remove(&ctx->bridge); 2308 2222 2309 2223 return 0; 2310 2224 }
+1 -4
drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
··· 221 221 struct drm_bridge bridge; 222 222 struct mipi_dsi_host dsi_host; 223 223 struct drm_bridge *panel_bridge; 224 - bool is_panel_bridge; 225 224 struct device *dev; 226 225 void __iomem *base; 227 226 ··· 296 297 bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DSI); 297 298 if (IS_ERR(bridge)) 298 299 return PTR_ERR(bridge); 299 - dsi->is_panel_bridge = true; 300 300 } 301 301 302 302 dsi->panel_bridge = bridge; ··· 310 312 { 311 313 struct dw_mipi_dsi *dsi = host_to_dsi(host); 312 314 313 - if (dsi->is_panel_bridge) 314 - drm_panel_bridge_remove(dsi->panel_bridge); 315 + drm_of_panel_bridge_remove(host->dev->of_node, 1, 0); 315 316 316 317 drm_bridge_remove(&dsi->bridge); 317 318
-3
drivers/gpu/drm/drm_atomic.c
··· 182 182 for (i = 0; i < state->num_private_objs; i++) { 183 183 struct drm_private_obj *obj = state->private_objs[i].ptr; 184 184 185 - if (!obj) 186 - continue; 187 - 188 185 obj->funcs->atomic_destroy_state(obj, 189 186 state->private_objs[i].state); 190 187 state->private_objs[i].ptr = NULL;
+1
drivers/gpu/drm/drm_atomic_helper.c
··· 3052 3052 drm_modeset_backoff(&ctx); 3053 3053 } 3054 3054 3055 + drm_atomic_state_put(state); 3055 3056 drm_modeset_drop_locks(&ctx); 3056 3057 drm_modeset_acquire_fini(&ctx); 3057 3058
+5 -2
drivers/gpu/drm/drm_dp_helper.c
··· 137 137 u8 drm_dp_link_rate_to_bw_code(int link_rate) 138 138 { 139 139 switch (link_rate) { 140 - case 162000: 141 140 default: 141 + WARN(1, "unknown DP link rate %d, using %x\n", link_rate, 142 + DP_LINK_BW_1_62); 143 + case 162000: 142 144 return DP_LINK_BW_1_62; 143 145 case 270000: 144 146 return DP_LINK_BW_2_7; ··· 153 151 int drm_dp_bw_code_to_link_rate(u8 link_bw) 154 152 { 155 153 switch (link_bw) { 156 - case DP_LINK_BW_1_62: 157 154 default: 155 + WARN(1, "unknown DP link BW code %x, using 162000\n", link_bw); 156 + case DP_LINK_BW_1_62: 158 157 return 162000; 159 158 case DP_LINK_BW_2_7: 160 159 return 270000;
+52 -30
drivers/gpu/drm/drm_gem_framebuffer_helper.c
··· 27 27 * DOC: overview 28 28 * 29 29 * This library provides helpers for drivers that don't subclass 30 - * &drm_framebuffer and and use &drm_gem_object for their backing storage. 30 + * &drm_framebuffer and use &drm_gem_object for their backing storage. 31 31 * 32 32 * Drivers without additional needs to validate framebuffers can simply use 33 - * drm_gem_fb_create() and everything is wired up automatically. But all 34 - * parts can be used individually. 33 + * drm_gem_fb_create() and everything is wired up automatically. Other drivers 34 + * can use all parts independently. 35 35 */ 36 36 37 37 /** 38 - * drm_gem_fb_get_obj() - Get GEM object for framebuffer 39 - * @fb: The framebuffer 40 - * @plane: Which plane 38 + * drm_gem_fb_get_obj() - Get GEM object backing the framebuffer 39 + * @fb: Framebuffer 40 + * @plane: Plane index 41 41 * 42 - * Returns the GEM object for given framebuffer. 42 + * No additional reference is taken beyond the one that the &drm_frambuffer 43 + * already holds. 44 + * 45 + * Returns: 46 + * Pointer to &drm_gem_object for the given framebuffer and plane index or NULL 47 + * if it does not exist. 43 48 */ 44 49 struct drm_gem_object *drm_gem_fb_get_obj(struct drm_framebuffer *fb, 45 50 unsigned int plane) ··· 87 82 88 83 /** 89 84 * drm_gem_fb_destroy - Free GEM backed framebuffer 90 - * @fb: DRM framebuffer 85 + * @fb: Framebuffer 91 86 * 92 87 * Frees a GEM backed framebuffer with its backing buffer(s) and the structure 93 88 * itself. Drivers can use this as their &drm_framebuffer_funcs->destroy ··· 107 102 108 103 /** 109 104 * drm_gem_fb_create_handle - Create handle for GEM backed framebuffer 110 - * @fb: DRM framebuffer 111 - * @file: drm file 112 - * @handle: handle created 105 + * @fb: Framebuffer 106 + * @file: DRM file to register the handle for 107 + * @handle: Pointer to return the created handle 113 108 * 109 + * This function creates a handle for the GEM object backing the framebuffer. 114 110 * Drivers can use this as their &drm_framebuffer_funcs->create_handle 115 - * callback. 111 + * callback. The GETFB IOCTL calls into this callback. 116 112 * 117 113 * Returns: 118 114 * 0 on success or a negative error code on failure. ··· 126 120 EXPORT_SYMBOL(drm_gem_fb_create_handle); 127 121 128 122 /** 129 - * drm_gem_fb_create_with_funcs() - helper function for the 123 + * drm_gem_fb_create_with_funcs() - Helper function for the 130 124 * &drm_mode_config_funcs.fb_create 131 125 * callback 132 126 * @dev: DRM device 133 - * @file: drm file for the ioctl call 134 - * @mode_cmd: metadata from the userspace fb creation request 127 + * @file: DRM file that holds the GEM handle(s) backing the framebuffer 128 + * @mode_cmd: Metadata from the userspace framebuffer creation request 135 129 * @funcs: vtable to be used for the new framebuffer object 136 130 * 137 131 * This can be used to set &drm_framebuffer_funcs for drivers that need the 138 132 * &drm_framebuffer_funcs.dirty callback. Use drm_gem_fb_create() if you don't 139 133 * need to change &drm_framebuffer_funcs. 140 134 * The function does buffer size validation. 135 + * 136 + * Returns: 137 + * Pointer to a &drm_framebuffer on success or an error pointer on failure. 141 138 */ 142 139 struct drm_framebuffer * 143 140 drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file, ··· 201 192 }; 202 193 203 194 /** 204 - * drm_gem_fb_create() - &drm_mode_config_funcs.fb_create callback function 195 + * drm_gem_fb_create() - Helper function for the 196 + * &drm_mode_config_funcs.fb_create callback 205 197 * @dev: DRM device 206 - * @file: drm file for the ioctl call 207 - * @mode_cmd: metadata from the userspace fb creation request 198 + * @file: DRM file that holds the GEM handle(s) backing the framebuffer 199 + * @mode_cmd: Metadata from the userspace framebuffer creation request 200 + * 201 + * This function creates a new framebuffer object described by 202 + * &drm_mode_fb_cmd2. This description includes handles for the buffer(s) 203 + * backing the framebuffer. 208 204 * 209 205 * If your hardware has special alignment or pitch requirements these should be 210 206 * checked before calling this function. The function does buffer size 211 207 * validation. Use drm_gem_fb_create_with_funcs() if you need to set 212 208 * &drm_framebuffer_funcs.dirty. 209 + * 210 + * Drivers can use this as their &drm_mode_config_funcs.fb_create callback. 211 + * The ADDFB2 IOCTL calls into this callback. 212 + * 213 + * Returns: 214 + * Pointer to a &drm_framebuffer on success or an error pointer on failure. 213 215 */ 214 216 struct drm_framebuffer * 215 217 drm_gem_fb_create(struct drm_device *dev, struct drm_file *file, ··· 232 212 EXPORT_SYMBOL_GPL(drm_gem_fb_create); 233 213 234 214 /** 235 - * drm_gem_fb_prepare_fb() - Prepare gem framebuffer 236 - * @plane: Which plane 237 - * @state: Plane state attach fence to 215 + * drm_gem_fb_prepare_fb() - Prepare a GEM backed framebuffer 216 + * @plane: Plane 217 + * @state: Plane state the fence will be attached to 238 218 * 239 - * This can be used as the &drm_plane_helper_funcs.prepare_fb hook. 240 - * 241 - * This function checks if the plane FB has an dma-buf attached, extracts 242 - * the exclusive fence and attaches it to plane state for the atomic helper 243 - * to wait on. 219 + * This function prepares a GEM backed framebuffer for scanout by checking if 220 + * the plane framebuffer has a DMA-BUF attached. If it does, it extracts the 221 + * exclusive fence and attaches it to the plane state for the atomic helper to 222 + * wait on. This function can be used as the &drm_plane_helper_funcs.prepare_fb 223 + * callback. 244 224 * 245 225 * There is no need for &drm_plane_helper_funcs.cleanup_fb hook for simple 246 226 * gem based framebuffer drivers which have their buffers always pinned in ··· 266 246 EXPORT_SYMBOL_GPL(drm_gem_fb_prepare_fb); 267 247 268 248 /** 269 - * drm_gem_fbdev_fb_create - Create a drm_framebuffer for fbdev emulation 249 + * drm_gem_fbdev_fb_create - Create a GEM backed &drm_framebuffer for fbdev 250 + * emulation 270 251 * @dev: DRM device 271 252 * @sizes: fbdev size description 272 - * @pitch_align: optional pitch alignment 253 + * @pitch_align: Optional pitch alignment 273 254 * @obj: GEM object backing the framebuffer 274 255 * @funcs: vtable to be used for the new framebuffer object 275 256 * 276 - * This function creates a framebuffer for use with fbdev emulation. 257 + * This function creates a framebuffer from a &drm_fb_helper_surface_size 258 + * description for use in the &drm_fb_helper_funcs.fb_probe callback. 277 259 * 278 260 * Returns: 279 - * Pointer to a drm_framebuffer on success or an error pointer on failure. 261 + * Pointer to a &drm_framebuffer on success or an error pointer on failure. 280 262 */ 281 263 struct drm_framebuffer * 282 264 drm_gem_fbdev_fb_create(struct drm_device *dev,
+33
drivers/gpu/drm/drm_of.c
··· 262 262 return ret; 263 263 } 264 264 EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge); 265 + 266 + #ifdef CONFIG_DRM_PANEL_BRIDGE 267 + /* 268 + * drm_of_panel_bridge_remove - remove panel bridge 269 + * @np: device tree node containing panel bridge output ports 270 + * 271 + * Remove the panel bridge of a given DT node's port and endpoint number 272 + * 273 + * Returns zero if successful, or one of the standard error codes if it fails. 274 + */ 275 + int drm_of_panel_bridge_remove(const struct device_node *np, 276 + int port, int endpoint) 277 + { 278 + struct drm_bridge *bridge; 279 + struct device_node *remote; 280 + 281 + remote = of_graph_get_remote_node(np, port, endpoint); 282 + if (!remote) 283 + return -ENODEV; 284 + 285 + bridge = of_drm_find_bridge(remote); 286 + drm_panel_bridge_remove(bridge); 287 + 288 + return 0; 289 + } 290 + #else 291 + int drm_of_panel_bridge_remove(const struct device_node *np, 292 + int port, int endpoint) 293 + { 294 + return -EINVAL; 295 + } 296 + #endif 297 + EXPORT_SYMBOL_GPL(drm_of_panel_bridge_remove);
+1 -1
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
··· 599 599 struct drm_crtc *crtc; 600 600 struct drm_encoder *encoder; 601 601 602 - if (pipe < 0 || pipe >= priv->num_crtcs) 602 + if (pipe >= priv->num_crtcs) 603 603 return 0; 604 604 605 605 crtc = priv->crtcs[pipe];
+8
drivers/gpu/drm/panel/Kconfig
··· 82 82 WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some 83 83 Xperia Z2 tablets 84 84 85 + config DRM_PANEL_RASPBERRYPI_TOUCHSCREEN 86 + tristate "Raspberry Pi 7-inch touchscreen panel" 87 + depends on DRM_MIPI_DSI 88 + help 89 + Say Y here if you want to enable support for the Raspberry 90 + Pi 7" Touchscreen. To compile this driver as a module, 91 + choose M here. 92 + 85 93 config DRM_PANEL_SAMSUNG_S6E3HA2 86 94 tristate "Samsung S6E3HA2 DSI video mode panel" 87 95 depends on OF
+1
drivers/gpu/drm/panel/Makefile
··· 5 5 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o 6 6 obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += panel-orisetech-otm8009a.o 7 7 obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o 8 + obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += panel-raspberrypi-touchscreen.o 8 9 obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o 9 10 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o 10 11 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
+514
drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
··· 1 + /* 2 + * Copyright © 2016-2017 Broadcom 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + * 8 + * Portions of this file (derived from panel-simple.c) are: 9 + * 10 + * Copyright (C) 2013, NVIDIA Corporation. All rights reserved. 11 + * 12 + * Permission is hereby granted, free of charge, to any person obtaining a 13 + * copy of this software and associated documentation files (the "Software"), 14 + * to deal in the Software without restriction, including without limitation 15 + * the rights to use, copy, modify, merge, publish, distribute, sub license, 16 + * and/or sell copies of the Software, and to permit persons to whom the 17 + * Software is furnished to do so, subject to the following conditions: 18 + * 19 + * The above copyright notice and this permission notice (including the 20 + * next paragraph) shall be included in all copies or substantial portions 21 + * of the Software. 22 + * 23 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 26 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 28 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 29 + * DEALINGS IN THE SOFTWARE. 30 + */ 31 + 32 + /** 33 + * Raspberry Pi 7" touchscreen panel driver. 34 + * 35 + * The 7" touchscreen consists of a DPI LCD panel, a Toshiba 36 + * TC358762XBG DSI-DPI bridge, and an I2C-connected Atmel ATTINY88-MUR 37 + * controlling power management, the LCD PWM, and initial register 38 + * setup of the Tohsiba. 39 + * 40 + * This driver controls the TC358762 and ATTINY88, presenting a DSI 41 + * device with a drm_panel. 42 + */ 43 + 44 + #include <linux/delay.h> 45 + #include <linux/err.h> 46 + #include <linux/fb.h> 47 + #include <linux/gpio.h> 48 + #include <linux/gpio/consumer.h> 49 + #include <linux/i2c.h> 50 + #include <linux/module.h> 51 + #include <linux/of.h> 52 + #include <linux/of_device.h> 53 + #include <linux/of_graph.h> 54 + #include <linux/pm.h> 55 + 56 + #include <drm/drm_panel.h> 57 + #include <drm/drmP.h> 58 + #include <drm/drm_crtc.h> 59 + #include <drm/drm_mipi_dsi.h> 60 + #include <drm/drm_panel.h> 61 + 62 + #define RPI_DSI_DRIVER_NAME "rpi-ts-dsi" 63 + 64 + /* I2C registers of the Atmel microcontroller. */ 65 + enum REG_ADDR { 66 + REG_ID = 0x80, 67 + REG_PORTA, /* BIT(2) for horizontal flip, BIT(3) for vertical flip */ 68 + REG_PORTB, 69 + REG_PORTC, 70 + REG_PORTD, 71 + REG_POWERON, 72 + REG_PWM, 73 + REG_DDRA, 74 + REG_DDRB, 75 + REG_DDRC, 76 + REG_DDRD, 77 + REG_TEST, 78 + REG_WR_ADDRL, 79 + REG_WR_ADDRH, 80 + REG_READH, 81 + REG_READL, 82 + REG_WRITEH, 83 + REG_WRITEL, 84 + REG_ID2, 85 + }; 86 + 87 + /* DSI D-PHY Layer Registers */ 88 + #define D0W_DPHYCONTTX 0x0004 89 + #define CLW_DPHYCONTRX 0x0020 90 + #define D0W_DPHYCONTRX 0x0024 91 + #define D1W_DPHYCONTRX 0x0028 92 + #define COM_DPHYCONTRX 0x0038 93 + #define CLW_CNTRL 0x0040 94 + #define D0W_CNTRL 0x0044 95 + #define D1W_CNTRL 0x0048 96 + #define DFTMODE_CNTRL 0x0054 97 + 98 + /* DSI PPI Layer Registers */ 99 + #define PPI_STARTPPI 0x0104 100 + #define PPI_BUSYPPI 0x0108 101 + #define PPI_LINEINITCNT 0x0110 102 + #define PPI_LPTXTIMECNT 0x0114 103 + #define PPI_CLS_ATMR 0x0140 104 + #define PPI_D0S_ATMR 0x0144 105 + #define PPI_D1S_ATMR 0x0148 106 + #define PPI_D0S_CLRSIPOCOUNT 0x0164 107 + #define PPI_D1S_CLRSIPOCOUNT 0x0168 108 + #define CLS_PRE 0x0180 109 + #define D0S_PRE 0x0184 110 + #define D1S_PRE 0x0188 111 + #define CLS_PREP 0x01A0 112 + #define D0S_PREP 0x01A4 113 + #define D1S_PREP 0x01A8 114 + #define CLS_ZERO 0x01C0 115 + #define D0S_ZERO 0x01C4 116 + #define D1S_ZERO 0x01C8 117 + #define PPI_CLRFLG 0x01E0 118 + #define PPI_CLRSIPO 0x01E4 119 + #define HSTIMEOUT 0x01F0 120 + #define HSTIMEOUTENABLE 0x01F4 121 + 122 + /* DSI Protocol Layer Registers */ 123 + #define DSI_STARTDSI 0x0204 124 + #define DSI_BUSYDSI 0x0208 125 + #define DSI_LANEENABLE 0x0210 126 + # define DSI_LANEENABLE_CLOCK BIT(0) 127 + # define DSI_LANEENABLE_D0 BIT(1) 128 + # define DSI_LANEENABLE_D1 BIT(2) 129 + 130 + #define DSI_LANESTATUS0 0x0214 131 + #define DSI_LANESTATUS1 0x0218 132 + #define DSI_INTSTATUS 0x0220 133 + #define DSI_INTMASK 0x0224 134 + #define DSI_INTCLR 0x0228 135 + #define DSI_LPTXTO 0x0230 136 + #define DSI_MODE 0x0260 137 + #define DSI_PAYLOAD0 0x0268 138 + #define DSI_PAYLOAD1 0x026C 139 + #define DSI_SHORTPKTDAT 0x0270 140 + #define DSI_SHORTPKTREQ 0x0274 141 + #define DSI_BTASTA 0x0278 142 + #define DSI_BTACLR 0x027C 143 + 144 + /* DSI General Registers */ 145 + #define DSIERRCNT 0x0300 146 + #define DSISIGMOD 0x0304 147 + 148 + /* DSI Application Layer Registers */ 149 + #define APLCTRL 0x0400 150 + #define APLSTAT 0x0404 151 + #define APLERR 0x0408 152 + #define PWRMOD 0x040C 153 + #define RDPKTLN 0x0410 154 + #define PXLFMT 0x0414 155 + #define MEMWRCMD 0x0418 156 + 157 + /* LCDC/DPI Host Registers */ 158 + #define LCDCTRL 0x0420 159 + #define HSR 0x0424 160 + #define HDISPR 0x0428 161 + #define VSR 0x042C 162 + #define VDISPR 0x0430 163 + #define VFUEN 0x0434 164 + 165 + /* DBI-B Host Registers */ 166 + #define DBIBCTRL 0x0440 167 + 168 + /* SPI Master Registers */ 169 + #define SPICMR 0x0450 170 + #define SPITCR 0x0454 171 + 172 + /* System Controller Registers */ 173 + #define SYSSTAT 0x0460 174 + #define SYSCTRL 0x0464 175 + #define SYSPLL1 0x0468 176 + #define SYSPLL2 0x046C 177 + #define SYSPLL3 0x0470 178 + #define SYSPMCTRL 0x047C 179 + 180 + /* GPIO Registers */ 181 + #define GPIOC 0x0480 182 + #define GPIOO 0x0484 183 + #define GPIOI 0x0488 184 + 185 + /* I2C Registers */ 186 + #define I2CCLKCTRL 0x0490 187 + 188 + /* Chip/Rev Registers */ 189 + #define IDREG 0x04A0 190 + 191 + /* Debug Registers */ 192 + #define WCMDQUEUE 0x0500 193 + #define RCMDQUEUE 0x0504 194 + 195 + struct rpi_touchscreen { 196 + struct drm_panel base; 197 + struct mipi_dsi_device *dsi; 198 + struct i2c_client *i2c; 199 + }; 200 + 201 + static const struct drm_display_mode rpi_touchscreen_modes[] = { 202 + { 203 + /* Modeline comes from the Raspberry Pi firmware, with HFP=1 204 + * plugged in and clock re-computed from that. 205 + */ 206 + .clock = 25979400 / 1000, 207 + .hdisplay = 800, 208 + .hsync_start = 800 + 1, 209 + .hsync_end = 800 + 1 + 2, 210 + .htotal = 800 + 1 + 2 + 46, 211 + .vdisplay = 480, 212 + .vsync_start = 480 + 7, 213 + .vsync_end = 480 + 7 + 2, 214 + .vtotal = 480 + 7 + 2 + 21, 215 + .vrefresh = 60, 216 + }, 217 + }; 218 + 219 + static struct rpi_touchscreen *panel_to_ts(struct drm_panel *panel) 220 + { 221 + return container_of(panel, struct rpi_touchscreen, base); 222 + } 223 + 224 + static u8 rpi_touchscreen_i2c_read(struct rpi_touchscreen *ts, u8 reg) 225 + { 226 + return i2c_smbus_read_byte_data(ts->i2c, reg); 227 + } 228 + 229 + static void rpi_touchscreen_i2c_write(struct rpi_touchscreen *ts, 230 + u8 reg, u8 val) 231 + { 232 + int ret; 233 + 234 + ret = i2c_smbus_write_byte_data(ts->i2c, reg, val); 235 + if (ret) 236 + dev_err(&ts->dsi->dev, "I2C write failed: %d\n", ret); 237 + } 238 + 239 + static int rpi_touchscreen_write(struct rpi_touchscreen *ts, u16 reg, u32 val) 240 + { 241 + #if 0 242 + /* The firmware uses LP DSI transactions like this to bring up 243 + * the hardware, which should be faster than using I2C to then 244 + * pass to the Toshiba. However, I was unable to get it to 245 + * work. 246 + */ 247 + u8 msg[] = { 248 + reg, 249 + reg >> 8, 250 + val, 251 + val >> 8, 252 + val >> 16, 253 + val >> 24, 254 + }; 255 + 256 + mipi_dsi_dcs_write_buffer(ts->dsi, msg, sizeof(msg)); 257 + #else 258 + rpi_touchscreen_i2c_write(ts, REG_WR_ADDRH, reg >> 8); 259 + rpi_touchscreen_i2c_write(ts, REG_WR_ADDRL, reg); 260 + rpi_touchscreen_i2c_write(ts, REG_WRITEH, val >> 8); 261 + rpi_touchscreen_i2c_write(ts, REG_WRITEL, val); 262 + #endif 263 + 264 + return 0; 265 + } 266 + 267 + static int rpi_touchscreen_disable(struct drm_panel *panel) 268 + { 269 + struct rpi_touchscreen *ts = panel_to_ts(panel); 270 + 271 + rpi_touchscreen_i2c_write(ts, REG_PWM, 0); 272 + 273 + rpi_touchscreen_i2c_write(ts, REG_POWERON, 0); 274 + udelay(1); 275 + 276 + return 0; 277 + } 278 + 279 + static int rpi_touchscreen_noop(struct drm_panel *panel) 280 + { 281 + return 0; 282 + } 283 + 284 + static int rpi_touchscreen_enable(struct drm_panel *panel) 285 + { 286 + struct rpi_touchscreen *ts = panel_to_ts(panel); 287 + int i; 288 + 289 + rpi_touchscreen_i2c_write(ts, REG_POWERON, 1); 290 + /* Wait for nPWRDWN to go low to indicate poweron is done. */ 291 + for (i = 0; i < 100; i++) { 292 + if (rpi_touchscreen_i2c_read(ts, REG_PORTB) & 1) 293 + break; 294 + } 295 + 296 + rpi_touchscreen_write(ts, DSI_LANEENABLE, 297 + DSI_LANEENABLE_CLOCK | 298 + DSI_LANEENABLE_D0); 299 + rpi_touchscreen_write(ts, PPI_D0S_CLRSIPOCOUNT, 0x05); 300 + rpi_touchscreen_write(ts, PPI_D1S_CLRSIPOCOUNT, 0x05); 301 + rpi_touchscreen_write(ts, PPI_D0S_ATMR, 0x00); 302 + rpi_touchscreen_write(ts, PPI_D1S_ATMR, 0x00); 303 + rpi_touchscreen_write(ts, PPI_LPTXTIMECNT, 0x03); 304 + 305 + rpi_touchscreen_write(ts, SPICMR, 0x00); 306 + rpi_touchscreen_write(ts, LCDCTRL, 0x00100150); 307 + rpi_touchscreen_write(ts, SYSCTRL, 0x040f); 308 + msleep(100); 309 + 310 + rpi_touchscreen_write(ts, PPI_STARTPPI, 0x01); 311 + rpi_touchscreen_write(ts, DSI_STARTDSI, 0x01); 312 + msleep(100); 313 + 314 + /* Turn on the backlight. */ 315 + rpi_touchscreen_i2c_write(ts, REG_PWM, 255); 316 + 317 + /* Default to the same orientation as the closed source 318 + * firmware used for the panel. Runtime rotation 319 + * configuration will be supported using VC4's plane 320 + * orientation bits. 321 + */ 322 + rpi_touchscreen_i2c_write(ts, REG_PORTA, BIT(2)); 323 + 324 + return 0; 325 + } 326 + 327 + static int rpi_touchscreen_get_modes(struct drm_panel *panel) 328 + { 329 + struct drm_connector *connector = panel->connector; 330 + struct drm_device *drm = panel->drm; 331 + unsigned int i, num = 0; 332 + static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; 333 + 334 + for (i = 0; i < ARRAY_SIZE(rpi_touchscreen_modes); i++) { 335 + const struct drm_display_mode *m = &rpi_touchscreen_modes[i]; 336 + struct drm_display_mode *mode; 337 + 338 + mode = drm_mode_duplicate(drm, m); 339 + if (!mode) { 340 + dev_err(drm->dev, "failed to add mode %ux%u@%u\n", 341 + m->hdisplay, m->vdisplay, m->vrefresh); 342 + continue; 343 + } 344 + 345 + mode->type |= DRM_MODE_TYPE_DRIVER; 346 + 347 + if (i == 0) 348 + mode->type |= DRM_MODE_TYPE_PREFERRED; 349 + 350 + drm_mode_set_name(mode); 351 + 352 + drm_mode_probed_add(connector, mode); 353 + num++; 354 + } 355 + 356 + connector->display_info.bpc = 8; 357 + connector->display_info.width_mm = 154; 358 + connector->display_info.height_mm = 86; 359 + drm_display_info_set_bus_formats(&connector->display_info, 360 + &bus_format, 1); 361 + 362 + return num; 363 + } 364 + 365 + static const struct drm_panel_funcs rpi_touchscreen_funcs = { 366 + .disable = rpi_touchscreen_disable, 367 + .unprepare = rpi_touchscreen_noop, 368 + .prepare = rpi_touchscreen_noop, 369 + .enable = rpi_touchscreen_enable, 370 + .get_modes = rpi_touchscreen_get_modes, 371 + }; 372 + 373 + static int rpi_touchscreen_probe(struct i2c_client *i2c, 374 + const struct i2c_device_id *id) 375 + { 376 + struct device *dev = &i2c->dev; 377 + struct rpi_touchscreen *ts; 378 + struct device_node *endpoint, *dsi_host_node; 379 + struct mipi_dsi_host *host; 380 + int ret, ver; 381 + struct mipi_dsi_device_info info = { 382 + .type = RPI_DSI_DRIVER_NAME, 383 + .channel = 0, 384 + .node = NULL, 385 + }; 386 + 387 + ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); 388 + if (!ts) 389 + return -ENOMEM; 390 + 391 + i2c_set_clientdata(i2c, ts); 392 + 393 + ts->i2c = i2c; 394 + 395 + ver = rpi_touchscreen_i2c_read(ts, REG_ID); 396 + if (ver < 0) { 397 + dev_err(dev, "Atmel I2C read failed: %d\n", ver); 398 + return -ENODEV; 399 + } 400 + 401 + switch (ver) { 402 + case 0xde: /* ver 1 */ 403 + case 0xc3: /* ver 2 */ 404 + break; 405 + default: 406 + dev_err(dev, "Unknown Atmel firmware revision: 0x%02x\n", ver); 407 + return -ENODEV; 408 + } 409 + 410 + /* Turn off at boot, so we can cleanly sequence powering on. */ 411 + rpi_touchscreen_i2c_write(ts, REG_POWERON, 0); 412 + 413 + /* Look up the DSI host. It needs to probe before we do. */ 414 + endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); 415 + dsi_host_node = of_graph_get_remote_port_parent(endpoint); 416 + host = of_find_mipi_dsi_host_by_node(dsi_host_node); 417 + of_node_put(dsi_host_node); 418 + if (!host) { 419 + of_node_put(endpoint); 420 + return -EPROBE_DEFER; 421 + } 422 + 423 + info.node = of_graph_get_remote_port(endpoint); 424 + of_node_put(endpoint); 425 + 426 + ts->dsi = mipi_dsi_device_register_full(host, &info); 427 + if (IS_ERR(ts->dsi)) { 428 + dev_err(dev, "DSI device registration failed: %ld\n", 429 + PTR_ERR(ts->dsi)); 430 + return PTR_ERR(ts->dsi); 431 + } 432 + 433 + ts->base.dev = dev; 434 + ts->base.funcs = &rpi_touchscreen_funcs; 435 + 436 + /* This appears last, as it's what will unblock the DSI host 437 + * driver's component bind function. 438 + */ 439 + ret = drm_panel_add(&ts->base); 440 + if (ret) 441 + return ret; 442 + 443 + return 0; 444 + } 445 + 446 + static int rpi_touchscreen_remove(struct i2c_client *i2c) 447 + { 448 + struct rpi_touchscreen *ts = i2c_get_clientdata(i2c); 449 + 450 + mipi_dsi_detach(ts->dsi); 451 + 452 + drm_panel_remove(&ts->base); 453 + 454 + mipi_dsi_device_unregister(ts->dsi); 455 + kfree(ts->dsi); 456 + 457 + return 0; 458 + } 459 + 460 + static int rpi_touchscreen_dsi_probe(struct mipi_dsi_device *dsi) 461 + { 462 + int ret; 463 + 464 + dsi->mode_flags = (MIPI_DSI_MODE_VIDEO | 465 + MIPI_DSI_MODE_VIDEO_SYNC_PULSE | 466 + MIPI_DSI_MODE_LPM); 467 + dsi->format = MIPI_DSI_FMT_RGB888; 468 + dsi->lanes = 1; 469 + 470 + ret = mipi_dsi_attach(dsi); 471 + 472 + if (ret) 473 + dev_err(&dsi->dev, "failed to attach dsi to host: %d\n", ret); 474 + 475 + return ret; 476 + } 477 + 478 + static struct mipi_dsi_driver rpi_touchscreen_dsi_driver = { 479 + .driver.name = RPI_DSI_DRIVER_NAME, 480 + .probe = rpi_touchscreen_dsi_probe, 481 + }; 482 + 483 + static const struct of_device_id rpi_touchscreen_of_ids[] = { 484 + { .compatible = "raspberrypi,7inch-touchscreen-panel" }, 485 + { } /* sentinel */ 486 + }; 487 + MODULE_DEVICE_TABLE(of, rpi_touchscreen_of_ids); 488 + 489 + static struct i2c_driver rpi_touchscreen_driver = { 490 + .driver = { 491 + .name = "rpi_touchscreen", 492 + .of_match_table = rpi_touchscreen_of_ids, 493 + }, 494 + .probe = rpi_touchscreen_probe, 495 + .remove = rpi_touchscreen_remove, 496 + }; 497 + 498 + static int __init rpi_touchscreen_init(void) 499 + { 500 + mipi_dsi_driver_register(&rpi_touchscreen_dsi_driver); 501 + return i2c_add_driver(&rpi_touchscreen_driver); 502 + } 503 + module_init(rpi_touchscreen_init); 504 + 505 + static void __exit rpi_touchscreen_exit(void) 506 + { 507 + i2c_del_driver(&rpi_touchscreen_driver); 508 + mipi_dsi_driver_unregister(&rpi_touchscreen_dsi_driver); 509 + } 510 + module_exit(rpi_touchscreen_exit); 511 + 512 + MODULE_AUTHOR("Eric Anholt <eric@anholt.net>"); 513 + MODULE_DESCRIPTION("Raspberry Pi 7-inch touchscreen driver"); 514 + MODULE_LICENSE("GPL v2");
+5 -11
drivers/gpu/drm/stm/ltdc.c
··· 791 791 .destroy = drm_encoder_cleanup, 792 792 }; 793 793 794 - static int ltdc_encoder_init(struct drm_device *ddev) 794 + static int ltdc_encoder_init(struct drm_device *ddev, struct drm_bridge *bridge) 795 795 { 796 - struct ltdc_device *ldev = ddev->dev_private; 797 796 struct drm_encoder *encoder; 798 797 int ret; 799 798 ··· 806 807 drm_encoder_init(ddev, encoder, &ltdc_encoder_funcs, 807 808 DRM_MODE_ENCODER_DPI, NULL); 808 809 809 - ret = drm_bridge_attach(encoder, ldev->bridge, NULL); 810 + ret = drm_bridge_attach(encoder, bridge, NULL); 810 811 if (ret) { 811 812 drm_encoder_cleanup(encoder); 812 813 return -EINVAL; ··· 935 936 ret = PTR_ERR(bridge); 936 937 goto err; 937 938 } 938 - ldev->is_panel_bridge = true; 939 939 } 940 940 941 - ldev->bridge = bridge; 942 - 943 - ret = ltdc_encoder_init(ddev); 941 + ret = ltdc_encoder_init(ddev, bridge); 944 942 if (ret) { 945 943 DRM_ERROR("Failed to init encoder\n"); 946 944 goto err; ··· 968 972 return 0; 969 973 970 974 err: 971 - if (ldev->is_panel_bridge) 972 - drm_panel_bridge_remove(bridge); 975 + drm_panel_bridge_remove(bridge); 973 976 974 977 clk_disable_unprepare(ldev->pixel_clk); 975 978 ··· 981 986 982 987 DRM_DEBUG_DRIVER("\n"); 983 988 984 - if (ldev->is_panel_bridge) 985 - drm_panel_bridge_remove(ldev->bridge); 989 + drm_of_panel_bridge_remove(ddev->dev->of_node, 0, 0); 986 990 987 991 clk_disable_unprepare(ldev->pixel_clk); 988 992 }
-2
drivers/gpu/drm/stm/ltdc.h
··· 24 24 struct drm_fbdev_cma *fbdev; 25 25 void __iomem *regs; 26 26 struct clk *pixel_clk; /* lcd pixel clock */ 27 - struct drm_bridge *bridge; 28 - bool is_panel_bridge; 29 27 struct mutex err_lock; /* protecting error_status */ 30 28 struct ltdc_caps caps; 31 29 u32 error_status;
+107
drivers/gpu/drm/sun4i/sun4i_hdmi.h
··· 14 14 15 15 #include <drm/drm_connector.h> 16 16 #include <drm/drm_encoder.h> 17 + #include <linux/regmap.h> 17 18 18 19 #include <media/cec-pin.h> 19 20 ··· 59 58 #define SUN4I_HDMI_PAD_CTRL0_TXEN BIT(23) 60 59 61 60 #define SUN4I_HDMI_PAD_CTRL1_REG 0x204 61 + #define SUN4I_HDMI_PAD_CTRL1_UNKNOWN BIT(24) /* set on A31 */ 62 62 #define SUN4I_HDMI_PAD_CTRL1_AMP_OPT BIT(23) 63 63 #define SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT BIT(22) 64 64 #define SUN4I_HDMI_PAD_CTRL1_EMP_OPT BIT(20) 65 65 #define SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT BIT(19) 66 + #define SUN4I_HDMI_PAD_CTRL1_PWSCK BIT(18) 67 + #define SUN4I_HDMI_PAD_CTRL1_PWSDT BIT(17) 66 68 #define SUN4I_HDMI_PAD_CTRL1_REG_DEN BIT(15) 67 69 #define SUN4I_HDMI_PAD_CTRL1_REG_DENCK BIT(14) 68 70 #define SUN4I_HDMI_PAD_CTRL1_REG_EMP(n) (((n) & 7) << 10) ··· 156 152 157 153 #define SUN4I_HDMI_DDC_FIFO_SIZE 16 158 154 155 + /* A31 specific */ 156 + #define SUN6I_HDMI_DDC_CTRL_REG 0x500 157 + #define SUN6I_HDMI_DDC_CTRL_RESET BIT(31) 158 + #define SUN6I_HDMI_DDC_CTRL_START_CMD BIT(27) 159 + #define SUN6I_HDMI_DDC_CTRL_SDA_ENABLE BIT(6) 160 + #define SUN6I_HDMI_DDC_CTRL_SCL_ENABLE BIT(4) 161 + #define SUN6I_HDMI_DDC_CTRL_ENABLE BIT(0) 162 + 163 + #define SUN6I_HDMI_DDC_CMD_REG 0x508 164 + #define SUN6I_HDMI_DDC_CMD_BYTE_COUNT(count) ((count) << 16) 165 + /* command types in lower 3 bits are the same as sun4i */ 166 + 167 + #define SUN6I_HDMI_DDC_ADDR_REG 0x50c 168 + #define SUN6I_HDMI_DDC_ADDR_SEGMENT(seg) (((seg) & 0xff) << 24) 169 + #define SUN6I_HDMI_DDC_ADDR_EDDC(addr) (((addr) & 0xff) << 16) 170 + #define SUN6I_HDMI_DDC_ADDR_OFFSET(off) (((off) & 0xff) << 8) 171 + #define SUN6I_HDMI_DDC_ADDR_SLAVE(addr) (((addr) & 0xff) << 1) 172 + 173 + #define SUN6I_HDMI_DDC_INT_STATUS_REG 0x514 174 + #define SUN6I_HDMI_DDC_INT_STATUS_TIMEOUT BIT(8) 175 + /* lower 8 bits are the same as sun4i */ 176 + 177 + #define SUN6I_HDMI_DDC_FIFO_CTRL_REG 0x518 178 + #define SUN6I_HDMI_DDC_FIFO_CTRL_CLEAR BIT(15) 179 + /* lower 9 bits are the same as sun4i */ 180 + 181 + #define SUN6I_HDMI_DDC_CLK_REG 0x520 182 + /* DDC CLK bit fields are the same, but the formula is not */ 183 + 184 + #define SUN6I_HDMI_DDC_FIFO_DATA_REG 0x580 185 + 159 186 enum sun4i_hdmi_pkt_type { 160 187 SUN4I_HDMI_PKT_AVI = 2, 161 188 SUN4I_HDMI_PKT_END = 15, 189 + }; 190 + 191 + struct sun4i_hdmi_variant { 192 + bool has_ddc_parent_clk; 193 + bool has_reset_control; 194 + 195 + u32 pad_ctrl0_init_val; 196 + u32 pad_ctrl1_init_val; 197 + u32 pll_ctrl_init_val; 198 + 199 + struct reg_field ddc_clk_reg; 200 + u8 ddc_clk_pre_divider; 201 + u8 ddc_clk_m_offset; 202 + 203 + u8 tmds_clk_div_offset; 204 + 205 + /* Register fields for I2C adapter */ 206 + struct reg_field field_ddc_en; 207 + struct reg_field field_ddc_start; 208 + struct reg_field field_ddc_reset; 209 + struct reg_field field_ddc_addr_reg; 210 + struct reg_field field_ddc_slave_addr; 211 + struct reg_field field_ddc_int_mask; 212 + struct reg_field field_ddc_int_status; 213 + struct reg_field field_ddc_fifo_clear; 214 + struct reg_field field_ddc_fifo_rx_thres; 215 + struct reg_field field_ddc_fifo_tx_thres; 216 + struct reg_field field_ddc_byte_count; 217 + struct reg_field field_ddc_cmd; 218 + struct reg_field field_ddc_sda_en; 219 + struct reg_field field_ddc_sck_en; 220 + 221 + /* DDC FIFO register offset */ 222 + u32 ddc_fifo_reg; 223 + 224 + /* 225 + * DDC FIFO threshold boundary conditions 226 + * 227 + * This is used to cope with the threshold boundary condition 228 + * being slightly different on sun5i and sun6i. 229 + * 230 + * On sun5i the threshold is exclusive, i.e. does not include, 231 + * the value of the threshold. ( > for RX; < for TX ) 232 + * On sun6i the threshold is inclusive, i.e. includes, the 233 + * value of the threshold. ( >= for RX; <= for TX ) 234 + */ 235 + bool ddc_fifo_thres_incl; 236 + 237 + bool ddc_fifo_has_dir; 162 238 }; 163 239 164 240 struct sun4i_hdmi { ··· 247 163 struct device *dev; 248 164 249 165 void __iomem *base; 166 + struct regmap *regmap; 167 + 168 + /* Reset control */ 169 + struct reset_control *reset; 250 170 251 171 /* Parent clocks */ 252 172 struct clk *bus_clk; 253 173 struct clk *mod_clk; 174 + struct clk *ddc_parent_clk; 254 175 struct clk *pll0_clk; 255 176 struct clk *pll1_clk; 256 177 ··· 265 176 266 177 struct i2c_adapter *i2c; 267 178 179 + /* Regmap fields for I2C adapter */ 180 + struct regmap_field *field_ddc_en; 181 + struct regmap_field *field_ddc_start; 182 + struct regmap_field *field_ddc_reset; 183 + struct regmap_field *field_ddc_addr_reg; 184 + struct regmap_field *field_ddc_slave_addr; 185 + struct regmap_field *field_ddc_int_mask; 186 + struct regmap_field *field_ddc_int_status; 187 + struct regmap_field *field_ddc_fifo_clear; 188 + struct regmap_field *field_ddc_fifo_rx_thres; 189 + struct regmap_field *field_ddc_fifo_tx_thres; 190 + struct regmap_field *field_ddc_byte_count; 191 + struct regmap_field *field_ddc_cmd; 192 + struct regmap_field *field_ddc_sda_en; 193 + struct regmap_field *field_ddc_sck_en; 194 + 268 195 struct sun4i_drv *drv; 269 196 270 197 bool hdmi_monitor; 271 198 struct cec_adapter *cec_adap; 199 + 200 + const struct sun4i_hdmi_variant *variant; 272 201 }; 273 202 274 203 int sun4i_ddc_create(struct sun4i_hdmi *hdmi, struct clk *clk);
+29 -9
drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
··· 11 11 */ 12 12 13 13 #include <linux/clk-provider.h> 14 + #include <linux/regmap.h> 14 15 15 16 #include "sun4i_tcon.h" 16 17 #include "sun4i_hdmi.h" ··· 19 18 struct sun4i_ddc { 20 19 struct clk_hw hw; 21 20 struct sun4i_hdmi *hdmi; 21 + struct regmap_field *reg; 22 + u8 pre_div; 23 + u8 m_offset; 22 24 }; 23 25 24 26 static inline struct sun4i_ddc *hw_to_ddc(struct clk_hw *hw) ··· 31 27 32 28 static unsigned long sun4i_ddc_calc_divider(unsigned long rate, 33 29 unsigned long parent_rate, 30 + const u8 pre_div, 31 + const u8 m_offset, 34 32 u8 *m, u8 *n) 35 33 { 36 34 unsigned long best_rate = 0; ··· 42 36 for (_n = 0; _n < 8; _n++) { 43 37 unsigned long tmp_rate; 44 38 45 - tmp_rate = (((parent_rate / 2) / 10) >> _n) / (_m + 1); 39 + tmp_rate = (((parent_rate / pre_div) / 10) >> _n) / 40 + (_m + m_offset); 46 41 47 42 if (tmp_rate > rate) 48 43 continue; ··· 67 60 static long sun4i_ddc_round_rate(struct clk_hw *hw, unsigned long rate, 68 61 unsigned long *prate) 69 62 { 70 - return sun4i_ddc_calc_divider(rate, *prate, NULL, NULL); 63 + struct sun4i_ddc *ddc = hw_to_ddc(hw); 64 + 65 + return sun4i_ddc_calc_divider(rate, *prate, ddc->pre_div, 66 + ddc->m_offset, NULL, NULL); 71 67 } 72 68 73 69 static unsigned long sun4i_ddc_recalc_rate(struct clk_hw *hw, 74 70 unsigned long parent_rate) 75 71 { 76 72 struct sun4i_ddc *ddc = hw_to_ddc(hw); 77 - u32 reg; 73 + unsigned int reg; 78 74 u8 m, n; 79 75 80 - reg = readl(ddc->hdmi->base + SUN4I_HDMI_DDC_CLK_REG); 81 - m = (reg >> 3) & 0x7; 76 + regmap_field_read(ddc->reg, &reg); 77 + m = (reg >> 3) & 0xf; 82 78 n = reg & 0x7; 83 79 84 - return (((parent_rate / 2) / 10) >> n) / (m + 1); 80 + return (((parent_rate / ddc->pre_div) / 10) >> n) / 81 + (m + ddc->m_offset); 85 82 } 86 83 87 84 static int sun4i_ddc_set_rate(struct clk_hw *hw, unsigned long rate, ··· 94 83 struct sun4i_ddc *ddc = hw_to_ddc(hw); 95 84 u8 div_m, div_n; 96 85 97 - sun4i_ddc_calc_divider(rate, parent_rate, &div_m, &div_n); 86 + sun4i_ddc_calc_divider(rate, parent_rate, ddc->pre_div, 87 + ddc->m_offset, &div_m, &div_n); 98 88 99 - writel(SUN4I_HDMI_DDC_CLK_M(div_m) | SUN4I_HDMI_DDC_CLK_N(div_n), 100 - ddc->hdmi->base + SUN4I_HDMI_DDC_CLK_REG); 89 + regmap_field_write(ddc->reg, 90 + SUN4I_HDMI_DDC_CLK_M(div_m) | 91 + SUN4I_HDMI_DDC_CLK_N(div_n)); 101 92 102 93 return 0; 103 94 } ··· 124 111 if (!ddc) 125 112 return -ENOMEM; 126 113 114 + ddc->reg = devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 115 + hdmi->variant->ddc_clk_reg); 116 + if (IS_ERR(ddc->reg)) 117 + return PTR_ERR(ddc->reg); 118 + 127 119 init.name = "hdmi-ddc"; 128 120 init.ops = &sun4i_ddc_ops; 129 121 init.parent_names = &parent_name; ··· 136 118 137 119 ddc->hdmi = hdmi; 138 120 ddc->hw.init = &init; 121 + ddc->pre_div = hdmi->variant->ddc_clk_pre_divider; 122 + ddc->m_offset = hdmi->variant->ddc_clk_m_offset; 139 123 140 124 hdmi->ddc_clk = devm_clk_register(hdmi->dev, &ddc->hw); 141 125 if (IS_ERR(hdmi->ddc_clk))
+179 -25
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
··· 20 20 #include <linux/clk.h> 21 21 #include <linux/component.h> 22 22 #include <linux/iopoll.h> 23 + #include <linux/of_device.h> 23 24 #include <linux/platform_device.h> 24 25 #include <linux/pm_runtime.h> 26 + #include <linux/regmap.h> 27 + #include <linux/reset.h> 25 28 26 29 #include "sun4i_backend.h" 27 30 #include "sun4i_crtc.h" ··· 270 267 }; 271 268 #endif 272 269 270 + #define SUN4I_HDMI_PAD_CTRL1_MASK (GENMASK(24, 7) | GENMASK(5, 0)) 271 + #define SUN4I_HDMI_PLL_CTRL_MASK (GENMASK(31, 8) | GENMASK(3, 0)) 272 + 273 + static const struct sun4i_hdmi_variant sun5i_variant = { 274 + .pad_ctrl0_init_val = SUN4I_HDMI_PAD_CTRL0_TXEN | 275 + SUN4I_HDMI_PAD_CTRL0_CKEN | 276 + SUN4I_HDMI_PAD_CTRL0_PWENG | 277 + SUN4I_HDMI_PAD_CTRL0_PWEND | 278 + SUN4I_HDMI_PAD_CTRL0_PWENC | 279 + SUN4I_HDMI_PAD_CTRL0_LDODEN | 280 + SUN4I_HDMI_PAD_CTRL0_LDOCEN | 281 + SUN4I_HDMI_PAD_CTRL0_BIASEN, 282 + .pad_ctrl1_init_val = SUN4I_HDMI_PAD_CTRL1_REG_AMP(6) | 283 + SUN4I_HDMI_PAD_CTRL1_REG_EMP(2) | 284 + SUN4I_HDMI_PAD_CTRL1_REG_DENCK | 285 + SUN4I_HDMI_PAD_CTRL1_REG_DEN | 286 + SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT | 287 + SUN4I_HDMI_PAD_CTRL1_EMP_OPT | 288 + SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT | 289 + SUN4I_HDMI_PAD_CTRL1_AMP_OPT, 290 + .pll_ctrl_init_val = SUN4I_HDMI_PLL_CTRL_VCO_S(8) | 291 + SUN4I_HDMI_PLL_CTRL_CS(7) | 292 + SUN4I_HDMI_PLL_CTRL_CP_S(15) | 293 + SUN4I_HDMI_PLL_CTRL_S(7) | 294 + SUN4I_HDMI_PLL_CTRL_VCO_GAIN(4) | 295 + SUN4I_HDMI_PLL_CTRL_SDIV2 | 296 + SUN4I_HDMI_PLL_CTRL_LDO2_EN | 297 + SUN4I_HDMI_PLL_CTRL_LDO1_EN | 298 + SUN4I_HDMI_PLL_CTRL_HV_IS_33 | 299 + SUN4I_HDMI_PLL_CTRL_BWS | 300 + SUN4I_HDMI_PLL_CTRL_PLL_EN, 301 + 302 + .ddc_clk_reg = REG_FIELD(SUN4I_HDMI_DDC_CLK_REG, 0, 6), 303 + .ddc_clk_pre_divider = 2, 304 + .ddc_clk_m_offset = 1, 305 + 306 + .field_ddc_en = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 31, 31), 307 + .field_ddc_start = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 30, 30), 308 + .field_ddc_reset = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 0, 0), 309 + .field_ddc_addr_reg = REG_FIELD(SUN4I_HDMI_DDC_ADDR_REG, 0, 31), 310 + .field_ddc_slave_addr = REG_FIELD(SUN4I_HDMI_DDC_ADDR_REG, 0, 6), 311 + .field_ddc_int_status = REG_FIELD(SUN4I_HDMI_DDC_INT_STATUS_REG, 0, 8), 312 + .field_ddc_fifo_clear = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 31, 31), 313 + .field_ddc_fifo_rx_thres = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 4, 7), 314 + .field_ddc_fifo_tx_thres = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 0, 3), 315 + .field_ddc_byte_count = REG_FIELD(SUN4I_HDMI_DDC_BYTE_COUNT_REG, 0, 9), 316 + .field_ddc_cmd = REG_FIELD(SUN4I_HDMI_DDC_CMD_REG, 0, 2), 317 + .field_ddc_sda_en = REG_FIELD(SUN4I_HDMI_DDC_LINE_CTRL_REG, 9, 9), 318 + .field_ddc_sck_en = REG_FIELD(SUN4I_HDMI_DDC_LINE_CTRL_REG, 8, 8), 319 + 320 + .ddc_fifo_reg = SUN4I_HDMI_DDC_FIFO_DATA_REG, 321 + .ddc_fifo_has_dir = true, 322 + }; 323 + 324 + static const struct sun4i_hdmi_variant sun6i_variant = { 325 + .has_ddc_parent_clk = true, 326 + .has_reset_control = true, 327 + .pad_ctrl0_init_val = 0xff | 328 + SUN4I_HDMI_PAD_CTRL0_TXEN | 329 + SUN4I_HDMI_PAD_CTRL0_CKEN | 330 + SUN4I_HDMI_PAD_CTRL0_PWENG | 331 + SUN4I_HDMI_PAD_CTRL0_PWEND | 332 + SUN4I_HDMI_PAD_CTRL0_PWENC | 333 + SUN4I_HDMI_PAD_CTRL0_LDODEN | 334 + SUN4I_HDMI_PAD_CTRL0_LDOCEN, 335 + .pad_ctrl1_init_val = SUN4I_HDMI_PAD_CTRL1_REG_AMP(6) | 336 + SUN4I_HDMI_PAD_CTRL1_REG_EMP(4) | 337 + SUN4I_HDMI_PAD_CTRL1_REG_DENCK | 338 + SUN4I_HDMI_PAD_CTRL1_REG_DEN | 339 + SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT | 340 + SUN4I_HDMI_PAD_CTRL1_EMP_OPT | 341 + SUN4I_HDMI_PAD_CTRL1_PWSDT | 342 + SUN4I_HDMI_PAD_CTRL1_PWSCK | 343 + SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT | 344 + SUN4I_HDMI_PAD_CTRL1_AMP_OPT | 345 + SUN4I_HDMI_PAD_CTRL1_UNKNOWN, 346 + .pll_ctrl_init_val = SUN4I_HDMI_PLL_CTRL_VCO_S(8) | 347 + SUN4I_HDMI_PLL_CTRL_CS(3) | 348 + SUN4I_HDMI_PLL_CTRL_CP_S(10) | 349 + SUN4I_HDMI_PLL_CTRL_S(4) | 350 + SUN4I_HDMI_PLL_CTRL_VCO_GAIN(4) | 351 + SUN4I_HDMI_PLL_CTRL_SDIV2 | 352 + SUN4I_HDMI_PLL_CTRL_LDO2_EN | 353 + SUN4I_HDMI_PLL_CTRL_LDO1_EN | 354 + SUN4I_HDMI_PLL_CTRL_HV_IS_33 | 355 + SUN4I_HDMI_PLL_CTRL_PLL_EN, 356 + 357 + .ddc_clk_reg = REG_FIELD(SUN6I_HDMI_DDC_CLK_REG, 0, 6), 358 + .ddc_clk_pre_divider = 1, 359 + .ddc_clk_m_offset = 2, 360 + 361 + .tmds_clk_div_offset = 1, 362 + 363 + .field_ddc_en = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 0, 0), 364 + .field_ddc_start = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 27, 27), 365 + .field_ddc_reset = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 31, 31), 366 + .field_ddc_addr_reg = REG_FIELD(SUN6I_HDMI_DDC_ADDR_REG, 1, 31), 367 + .field_ddc_slave_addr = REG_FIELD(SUN6I_HDMI_DDC_ADDR_REG, 1, 7), 368 + .field_ddc_int_status = REG_FIELD(SUN6I_HDMI_DDC_INT_STATUS_REG, 0, 8), 369 + .field_ddc_fifo_clear = REG_FIELD(SUN6I_HDMI_DDC_FIFO_CTRL_REG, 18, 18), 370 + .field_ddc_fifo_rx_thres = REG_FIELD(SUN6I_HDMI_DDC_FIFO_CTRL_REG, 4, 7), 371 + .field_ddc_fifo_tx_thres = REG_FIELD(SUN6I_HDMI_DDC_FIFO_CTRL_REG, 0, 3), 372 + .field_ddc_byte_count = REG_FIELD(SUN6I_HDMI_DDC_CMD_REG, 16, 25), 373 + .field_ddc_cmd = REG_FIELD(SUN6I_HDMI_DDC_CMD_REG, 0, 2), 374 + .field_ddc_sda_en = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 6, 6), 375 + .field_ddc_sck_en = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 4, 4), 376 + 377 + .ddc_fifo_reg = SUN6I_HDMI_DDC_FIFO_DATA_REG, 378 + .ddc_fifo_thres_incl = true, 379 + }; 380 + 381 + static const struct regmap_config sun4i_hdmi_regmap_config = { 382 + .reg_bits = 32, 383 + .val_bits = 32, 384 + .reg_stride = 4, 385 + .max_register = 0x580, 386 + }; 387 + 273 388 static int sun4i_hdmi_bind(struct device *dev, struct device *master, 274 389 void *data) 275 390 { ··· 406 285 hdmi->dev = dev; 407 286 hdmi->drv = drv; 408 287 288 + hdmi->variant = of_device_get_match_data(dev); 289 + if (!hdmi->variant) 290 + return -EINVAL; 291 + 409 292 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 410 293 hdmi->base = devm_ioremap_resource(dev, res); 411 294 if (IS_ERR(hdmi->base)) { ··· 417 292 return PTR_ERR(hdmi->base); 418 293 } 419 294 295 + if (hdmi->variant->has_reset_control) { 296 + hdmi->reset = devm_reset_control_get(dev, NULL); 297 + if (IS_ERR(hdmi->reset)) { 298 + dev_err(dev, "Couldn't get the HDMI reset control\n"); 299 + return PTR_ERR(hdmi->reset); 300 + } 301 + 302 + ret = reset_control_deassert(hdmi->reset); 303 + if (ret) { 304 + dev_err(dev, "Couldn't deassert HDMI reset\n"); 305 + return ret; 306 + } 307 + } 308 + 420 309 hdmi->bus_clk = devm_clk_get(dev, "ahb"); 421 310 if (IS_ERR(hdmi->bus_clk)) { 422 311 dev_err(dev, "Couldn't get the HDMI bus clock\n"); 423 - return PTR_ERR(hdmi->bus_clk); 312 + ret = PTR_ERR(hdmi->bus_clk); 313 + goto err_assert_reset; 424 314 } 425 315 clk_prepare_enable(hdmi->bus_clk); 426 316 427 317 hdmi->mod_clk = devm_clk_get(dev, "mod"); 428 318 if (IS_ERR(hdmi->mod_clk)) { 429 319 dev_err(dev, "Couldn't get the HDMI mod clock\n"); 430 - return PTR_ERR(hdmi->mod_clk); 320 + ret = PTR_ERR(hdmi->mod_clk); 321 + goto err_disable_bus_clk; 431 322 } 432 323 clk_prepare_enable(hdmi->mod_clk); 433 324 434 325 hdmi->pll0_clk = devm_clk_get(dev, "pll-0"); 435 326 if (IS_ERR(hdmi->pll0_clk)) { 436 327 dev_err(dev, "Couldn't get the HDMI PLL 0 clock\n"); 437 - return PTR_ERR(hdmi->pll0_clk); 328 + ret = PTR_ERR(hdmi->pll0_clk); 329 + goto err_disable_mod_clk; 438 330 } 439 331 440 332 hdmi->pll1_clk = devm_clk_get(dev, "pll-1"); 441 333 if (IS_ERR(hdmi->pll1_clk)) { 442 334 dev_err(dev, "Couldn't get the HDMI PLL 1 clock\n"); 443 - return PTR_ERR(hdmi->pll1_clk); 335 + ret = PTR_ERR(hdmi->pll1_clk); 336 + goto err_disable_mod_clk; 337 + } 338 + 339 + hdmi->regmap = devm_regmap_init_mmio(dev, hdmi->base, 340 + &sun4i_hdmi_regmap_config); 341 + if (IS_ERR(hdmi->regmap)) { 342 + dev_err(dev, "Couldn't create HDMI encoder regmap\n"); 343 + return PTR_ERR(hdmi->regmap); 444 344 } 445 345 446 346 ret = sun4i_tmds_create(hdmi); 447 347 if (ret) { 448 348 dev_err(dev, "Couldn't create the TMDS clock\n"); 449 - return ret; 349 + goto err_disable_mod_clk; 350 + } 351 + 352 + if (hdmi->variant->has_ddc_parent_clk) { 353 + hdmi->ddc_parent_clk = devm_clk_get(dev, "ddc"); 354 + if (IS_ERR(hdmi->ddc_parent_clk)) { 355 + dev_err(dev, "Couldn't get the HDMI DDC clock\n"); 356 + return PTR_ERR(hdmi->ddc_parent_clk); 357 + } 358 + } else { 359 + hdmi->ddc_parent_clk = hdmi->tmds_clk; 450 360 } 451 361 452 362 writel(SUN4I_HDMI_CTRL_ENABLE, hdmi->base + SUN4I_HDMI_CTRL_REG); 453 363 454 - writel(SUN4I_HDMI_PAD_CTRL0_TXEN | SUN4I_HDMI_PAD_CTRL0_CKEN | 455 - SUN4I_HDMI_PAD_CTRL0_PWENG | SUN4I_HDMI_PAD_CTRL0_PWEND | 456 - SUN4I_HDMI_PAD_CTRL0_PWENC | SUN4I_HDMI_PAD_CTRL0_LDODEN | 457 - SUN4I_HDMI_PAD_CTRL0_LDOCEN | SUN4I_HDMI_PAD_CTRL0_BIASEN, 364 + writel(hdmi->variant->pad_ctrl0_init_val, 458 365 hdmi->base + SUN4I_HDMI_PAD_CTRL0_REG); 459 366 460 367 /* ··· 496 339 */ 497 340 reg = readl(hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG); 498 341 reg &= SUN4I_HDMI_PAD_CTRL1_HALVE_CLK; 499 - reg |= SUN4I_HDMI_PAD_CTRL1_REG_AMP(6) | 500 - SUN4I_HDMI_PAD_CTRL1_REG_EMP(2) | 501 - SUN4I_HDMI_PAD_CTRL1_REG_DENCK | 502 - SUN4I_HDMI_PAD_CTRL1_REG_DEN | 503 - SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT | 504 - SUN4I_HDMI_PAD_CTRL1_EMP_OPT | 505 - SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT | 506 - SUN4I_HDMI_PAD_CTRL1_AMP_OPT; 342 + reg |= hdmi->variant->pad_ctrl1_init_val; 507 343 writel(reg, hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG); 508 344 509 345 reg = readl(hdmi->base + SUN4I_HDMI_PLL_CTRL_REG); 510 346 reg &= SUN4I_HDMI_PLL_CTRL_DIV_MASK; 511 - reg |= SUN4I_HDMI_PLL_CTRL_VCO_S(8) | SUN4I_HDMI_PLL_CTRL_CS(7) | 512 - SUN4I_HDMI_PLL_CTRL_CP_S(15) | SUN4I_HDMI_PLL_CTRL_S(7) | 513 - SUN4I_HDMI_PLL_CTRL_VCO_GAIN(4) | SUN4I_HDMI_PLL_CTRL_SDIV2 | 514 - SUN4I_HDMI_PLL_CTRL_LDO2_EN | SUN4I_HDMI_PLL_CTRL_LDO1_EN | 515 - SUN4I_HDMI_PLL_CTRL_HV_IS_33 | SUN4I_HDMI_PLL_CTRL_BWS | 516 - SUN4I_HDMI_PLL_CTRL_PLL_EN; 347 + reg |= hdmi->variant->pll_ctrl_init_val; 517 348 writel(reg, hdmi->base + SUN4I_HDMI_PLL_CTRL_REG); 518 349 519 350 ret = sun4i_hdmi_i2c_create(dev, hdmi); 520 351 if (ret) { 521 352 dev_err(dev, "Couldn't create the HDMI I2C adapter\n"); 522 - return ret; 353 + goto err_disable_mod_clk; 523 354 } 524 355 525 356 drm_encoder_helper_add(&hdmi->encoder, ··· 567 422 drm_encoder_cleanup(&hdmi->encoder); 568 423 err_del_i2c_adapter: 569 424 i2c_del_adapter(hdmi->i2c); 425 + err_disable_mod_clk: 426 + clk_disable_unprepare(hdmi->mod_clk); 427 + err_disable_bus_clk: 428 + clk_disable_unprepare(hdmi->bus_clk); 429 + err_assert_reset: 430 + reset_control_assert(hdmi->reset); 570 431 return ret; 571 432 } 572 433 ··· 585 434 drm_connector_cleanup(&hdmi->connector); 586 435 drm_encoder_cleanup(&hdmi->encoder); 587 436 i2c_del_adapter(hdmi->i2c); 437 + clk_disable_unprepare(hdmi->mod_clk); 438 + clk_disable_unprepare(hdmi->bus_clk); 588 439 } 589 440 590 441 static const struct component_ops sun4i_hdmi_ops = { ··· 607 454 } 608 455 609 456 static const struct of_device_id sun4i_hdmi_of_table[] = { 610 - { .compatible = "allwinner,sun5i-a10s-hdmi" }, 457 + { .compatible = "allwinner,sun5i-a10s-hdmi", .data = &sun5i_variant, }, 458 + { .compatible = "allwinner,sun6i-a31-hdmi", .data = &sun6i_variant, }, 611 459 { } 612 460 }; 613 461 MODULE_DEVICE_TABLE(of, sun4i_hdmi_of_table);
+164 -63
drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c
··· 25 25 26 26 /* FIFO request bit is set when FIFO level is above RX_THRESHOLD during read */ 27 27 #define RX_THRESHOLD SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES_MAX 28 - /* FIFO request bit is set when FIFO level is below TX_THRESHOLD during write */ 29 - #define TX_THRESHOLD 1 30 28 31 29 static int fifo_transfer(struct sun4i_hdmi *hdmi, u8 *buf, int len, bool read) 32 30 { ··· 37 39 SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST | 38 40 SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE; 39 41 u32 reg; 42 + /* 43 + * If threshold is inclusive, then the FIFO may only have 44 + * RX_THRESHOLD number of bytes, instead of RX_THRESHOLD + 1. 45 + */ 46 + int read_len = RX_THRESHOLD + 47 + (hdmi->variant->ddc_fifo_thres_incl ? 0 : 1); 40 48 41 - /* Limit transfer length by FIFO threshold */ 42 - len = min_t(int, len, read ? (RX_THRESHOLD + 1) : 43 - (SUN4I_HDMI_DDC_FIFO_SIZE - TX_THRESHOLD + 1)); 49 + /* 50 + * Limit transfer length by FIFO threshold or FIFO size. 51 + * For TX the threshold is for an empty FIFO. 52 + */ 53 + len = min_t(int, len, read ? read_len : SUN4I_HDMI_DDC_FIFO_SIZE); 44 54 45 55 /* Wait until error, FIFO request bit set or transfer complete */ 46 - if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG, reg, 47 - reg & mask, len * byte_time_ns, 100000)) 56 + if (regmap_field_read_poll_timeout(hdmi->field_ddc_int_status, reg, 57 + reg & mask, len * byte_time_ns, 58 + 100000)) 48 59 return -ETIMEDOUT; 49 60 50 61 if (reg & SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK) 51 62 return -EIO; 52 63 53 64 if (read) 54 - readsb(hdmi->base + SUN4I_HDMI_DDC_FIFO_DATA_REG, buf, len); 65 + readsb(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len); 55 66 else 56 - writesb(hdmi->base + SUN4I_HDMI_DDC_FIFO_DATA_REG, buf, len); 67 + writesb(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len); 57 68 58 - /* Clear FIFO request bit */ 59 - writel(SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST, 60 - hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); 69 + /* Clear FIFO request bit by forcing a write to that bit */ 70 + regmap_field_force_write(hdmi->field_ddc_int_status, 71 + SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST); 61 72 62 73 return len; 63 74 } ··· 77 70 u32 reg; 78 71 79 72 /* Set FIFO direction */ 80 - reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 81 - reg &= ~SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK; 82 - reg |= (msg->flags & I2C_M_RD) ? 83 - SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ : 84 - SUN4I_HDMI_DDC_CTRL_FIFO_DIR_WRITE; 85 - writel(reg, hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 73 + if (hdmi->variant->ddc_fifo_has_dir) { 74 + reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 75 + reg &= ~SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK; 76 + reg |= (msg->flags & I2C_M_RD) ? 77 + SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ : 78 + SUN4I_HDMI_DDC_CTRL_FIFO_DIR_WRITE; 79 + writel(reg, hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 80 + } 81 + 82 + /* Clear address register (not cleared by soft reset) */ 83 + regmap_field_write(hdmi->field_ddc_addr_reg, 0); 86 84 87 85 /* Set I2C address */ 88 - writel(SUN4I_HDMI_DDC_ADDR_SLAVE(msg->addr), 89 - hdmi->base + SUN4I_HDMI_DDC_ADDR_REG); 86 + regmap_field_write(hdmi->field_ddc_slave_addr, msg->addr); 90 87 91 - /* Set FIFO RX/TX thresholds and clear FIFO */ 92 - reg = readl(hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG); 93 - reg |= SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR; 94 - reg &= ~SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES_MASK; 95 - reg |= SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES(RX_THRESHOLD); 96 - reg &= ~SUN4I_HDMI_DDC_FIFO_CTRL_TX_THRES_MASK; 97 - reg |= SUN4I_HDMI_DDC_FIFO_CTRL_TX_THRES(TX_THRESHOLD); 98 - writel(reg, hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG); 99 - if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG, 100 - reg, 101 - !(reg & SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR), 102 - 100, 2000)) 88 + /* 89 + * Set FIFO RX/TX thresholds and clear FIFO 90 + * 91 + * If threshold is inclusive, we can set the TX threshold to 92 + * 0 instead of 1. 93 + */ 94 + regmap_field_write(hdmi->field_ddc_fifo_tx_thres, 95 + hdmi->variant->ddc_fifo_thres_incl ? 0 : 1); 96 + regmap_field_write(hdmi->field_ddc_fifo_rx_thres, RX_THRESHOLD); 97 + regmap_field_write(hdmi->field_ddc_fifo_clear, 1); 98 + if (regmap_field_read_poll_timeout(hdmi->field_ddc_fifo_clear, 99 + reg, !reg, 100, 2000)) 103 100 return -EIO; 104 101 105 102 /* Set transfer length */ 106 - writel(msg->len, hdmi->base + SUN4I_HDMI_DDC_BYTE_COUNT_REG); 103 + regmap_field_write(hdmi->field_ddc_byte_count, msg->len); 107 104 108 105 /* Set command */ 109 - writel(msg->flags & I2C_M_RD ? 110 - SUN4I_HDMI_DDC_CMD_IMPLICIT_READ : 111 - SUN4I_HDMI_DDC_CMD_IMPLICIT_WRITE, 112 - hdmi->base + SUN4I_HDMI_DDC_CMD_REG); 106 + regmap_field_write(hdmi->field_ddc_cmd, 107 + msg->flags & I2C_M_RD ? 108 + SUN4I_HDMI_DDC_CMD_IMPLICIT_READ : 109 + SUN4I_HDMI_DDC_CMD_IMPLICIT_WRITE); 113 110 114 - /* Clear interrupt status bits */ 115 - writel(SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK | 116 - SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST | 117 - SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE, 118 - hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); 111 + /* Clear interrupt status bits by forcing a write */ 112 + regmap_field_force_write(hdmi->field_ddc_int_status, 113 + SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK | 114 + SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST | 115 + SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE); 119 116 120 117 /* Start command */ 121 - reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 122 - writel(reg | SUN4I_HDMI_DDC_CTRL_START_CMD, 123 - hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 118 + regmap_field_write(hdmi->field_ddc_start, 1); 124 119 125 120 /* Transfer bytes */ 126 121 for (i = 0; i < msg->len; i += len) { ··· 133 124 } 134 125 135 126 /* Wait for command to finish */ 136 - if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG, 137 - reg, 138 - !(reg & SUN4I_HDMI_DDC_CTRL_START_CMD), 139 - 100, 100000)) 127 + if (regmap_field_read_poll_timeout(hdmi->field_ddc_start, 128 + reg, !reg, 100, 100000)) 140 129 return -EIO; 141 130 142 131 /* Check for errors */ 143 - reg = readl(hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); 132 + regmap_field_read(hdmi->field_ddc_int_status, &reg); 144 133 if ((reg & SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK) || 145 134 !(reg & SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE)) { 146 135 return -EIO; ··· 161 154 return -EINVAL; 162 155 } 163 156 164 - /* Reset I2C controller */ 165 - writel(SUN4I_HDMI_DDC_CTRL_ENABLE | SUN4I_HDMI_DDC_CTRL_RESET, 166 - hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 167 - if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG, reg, 168 - !(reg & SUN4I_HDMI_DDC_CTRL_RESET), 169 - 100, 2000)) 170 - return -EIO; 171 - 172 - writel(SUN4I_HDMI_DDC_LINE_CTRL_SDA_ENABLE | 173 - SUN4I_HDMI_DDC_LINE_CTRL_SCL_ENABLE, 174 - hdmi->base + SUN4I_HDMI_DDC_LINE_CTRL_REG); 175 - 157 + /* DDC clock needs to be enabled for the module to work */ 176 158 clk_prepare_enable(hdmi->ddc_clk); 177 159 clk_set_rate(hdmi->ddc_clk, 100000); 160 + 161 + /* Reset I2C controller */ 162 + regmap_field_write(hdmi->field_ddc_en, 1); 163 + regmap_field_write(hdmi->field_ddc_reset, 1); 164 + if (regmap_field_read_poll_timeout(hdmi->field_ddc_reset, 165 + reg, !reg, 100, 2000)) { 166 + clk_disable_unprepare(hdmi->ddc_clk); 167 + return -EIO; 168 + } 169 + 170 + regmap_field_write(hdmi->field_ddc_sck_en, 1); 171 + regmap_field_write(hdmi->field_ddc_sda_en, 1); 178 172 179 173 for (i = 0; i < num; i++) { 180 174 err = xfer_msg(hdmi, &msgs[i]); ··· 199 191 .functionality = sun4i_hdmi_i2c_func, 200 192 }; 201 193 194 + static int sun4i_hdmi_init_regmap_fields(struct sun4i_hdmi *hdmi) 195 + { 196 + hdmi->field_ddc_en = 197 + devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 198 + hdmi->variant->field_ddc_en); 199 + if (IS_ERR(hdmi->field_ddc_en)) 200 + return PTR_ERR(hdmi->field_ddc_en); 201 + 202 + hdmi->field_ddc_start = 203 + devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 204 + hdmi->variant->field_ddc_start); 205 + if (IS_ERR(hdmi->field_ddc_start)) 206 + return PTR_ERR(hdmi->field_ddc_start); 207 + 208 + hdmi->field_ddc_reset = 209 + devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 210 + hdmi->variant->field_ddc_reset); 211 + if (IS_ERR(hdmi->field_ddc_reset)) 212 + return PTR_ERR(hdmi->field_ddc_reset); 213 + 214 + hdmi->field_ddc_addr_reg = 215 + devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 216 + hdmi->variant->field_ddc_addr_reg); 217 + if (IS_ERR(hdmi->field_ddc_addr_reg)) 218 + return PTR_ERR(hdmi->field_ddc_addr_reg); 219 + 220 + hdmi->field_ddc_slave_addr = 221 + devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 222 + hdmi->variant->field_ddc_slave_addr); 223 + if (IS_ERR(hdmi->field_ddc_slave_addr)) 224 + return PTR_ERR(hdmi->field_ddc_slave_addr); 225 + 226 + hdmi->field_ddc_int_mask = 227 + devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 228 + hdmi->variant->field_ddc_int_mask); 229 + if (IS_ERR(hdmi->field_ddc_int_mask)) 230 + return PTR_ERR(hdmi->field_ddc_int_mask); 231 + 232 + hdmi->field_ddc_int_status = 233 + devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 234 + hdmi->variant->field_ddc_int_status); 235 + if (IS_ERR(hdmi->field_ddc_int_status)) 236 + return PTR_ERR(hdmi->field_ddc_int_status); 237 + 238 + hdmi->field_ddc_fifo_clear = 239 + devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 240 + hdmi->variant->field_ddc_fifo_clear); 241 + if (IS_ERR(hdmi->field_ddc_fifo_clear)) 242 + return PTR_ERR(hdmi->field_ddc_fifo_clear); 243 + 244 + hdmi->field_ddc_fifo_rx_thres = 245 + devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 246 + hdmi->variant->field_ddc_fifo_rx_thres); 247 + if (IS_ERR(hdmi->field_ddc_fifo_rx_thres)) 248 + return PTR_ERR(hdmi->field_ddc_fifo_rx_thres); 249 + 250 + hdmi->field_ddc_fifo_tx_thres = 251 + devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 252 + hdmi->variant->field_ddc_fifo_tx_thres); 253 + if (IS_ERR(hdmi->field_ddc_fifo_tx_thres)) 254 + return PTR_ERR(hdmi->field_ddc_fifo_tx_thres); 255 + 256 + hdmi->field_ddc_byte_count = 257 + devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 258 + hdmi->variant->field_ddc_byte_count); 259 + if (IS_ERR(hdmi->field_ddc_byte_count)) 260 + return PTR_ERR(hdmi->field_ddc_byte_count); 261 + 262 + hdmi->field_ddc_cmd = 263 + devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 264 + hdmi->variant->field_ddc_cmd); 265 + if (IS_ERR(hdmi->field_ddc_cmd)) 266 + return PTR_ERR(hdmi->field_ddc_cmd); 267 + 268 + hdmi->field_ddc_sda_en = 269 + devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 270 + hdmi->variant->field_ddc_sda_en); 271 + if (IS_ERR(hdmi->field_ddc_sda_en)) 272 + return PTR_ERR(hdmi->field_ddc_sda_en); 273 + 274 + hdmi->field_ddc_sck_en = 275 + devm_regmap_field_alloc(hdmi->dev, hdmi->regmap, 276 + hdmi->variant->field_ddc_sck_en); 277 + if (IS_ERR(hdmi->field_ddc_sck_en)) 278 + return PTR_ERR(hdmi->field_ddc_sck_en); 279 + 280 + return 0; 281 + } 282 + 202 283 int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi) 203 284 { 204 285 struct i2c_adapter *adap; 205 286 int ret = 0; 206 287 207 - ret = sun4i_ddc_create(hdmi, hdmi->tmds_clk); 288 + ret = sun4i_ddc_create(hdmi, hdmi->ddc_parent_clk); 289 + if (ret) 290 + return ret; 291 + 292 + ret = sun4i_hdmi_init_regmap_fields(hdmi); 208 293 if (ret) 209 294 return ret; 210 295
+36 -24
drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
··· 18 18 struct sun4i_tmds { 19 19 struct clk_hw hw; 20 20 struct sun4i_hdmi *hdmi; 21 + 22 + u8 div_offset; 21 23 }; 22 24 23 25 static inline struct sun4i_tmds *hw_to_tmds(struct clk_hw *hw) ··· 30 28 31 29 static unsigned long sun4i_tmds_calc_divider(unsigned long rate, 32 30 unsigned long parent_rate, 31 + u8 div_offset, 33 32 u8 *div, 34 33 bool *half) 35 34 { ··· 38 35 u8 best_m = 0, m; 39 36 bool is_double; 40 37 41 - for (m = 1; m < 16; m++) { 38 + for (m = div_offset ?: 1; m < (16 + div_offset); m++) { 42 39 u8 d; 43 40 44 41 for (d = 1; d < 3; d++) { ··· 70 67 static int sun4i_tmds_determine_rate(struct clk_hw *hw, 71 68 struct clk_rate_request *req) 72 69 { 73 - struct clk_hw *parent; 70 + struct sun4i_tmds *tmds = hw_to_tmds(hw); 71 + struct clk_hw *parent = NULL; 74 72 unsigned long best_parent = 0; 75 73 unsigned long rate = req->rate; 76 74 int best_div = 1, best_half = 1; 77 - int i, j; 75 + int i, j, p; 78 76 79 77 /* 80 78 * We only consider PLL3, since the TCON is very likely to be ··· 83 79 * clock, so we should not need to do anything. 84 80 */ 85 81 86 - parent = clk_hw_get_parent_by_index(hw, 0); 87 - if (!parent) 88 - return -EINVAL; 82 + for (p = 0; p < clk_hw_get_num_parents(hw); p++) { 83 + parent = clk_hw_get_parent_by_index(hw, p); 84 + if (!parent) 85 + continue; 89 86 90 - for (i = 1; i < 3; i++) { 91 - for (j = 1; j < 16; j++) { 92 - unsigned long ideal = rate * i * j; 93 - unsigned long rounded; 87 + for (i = 1; i < 3; i++) { 88 + for (j = tmds->div_offset ?: 1; 89 + j < (16 + tmds->div_offset); j++) { 90 + unsigned long ideal = rate * i * j; 91 + unsigned long rounded; 94 92 95 - rounded = clk_hw_round_rate(parent, ideal); 93 + rounded = clk_hw_round_rate(parent, ideal); 96 94 97 - if (rounded == ideal) { 98 - best_parent = rounded; 99 - best_half = i; 100 - best_div = j; 101 - goto out; 102 - } 95 + if (rounded == ideal) { 96 + best_parent = rounded; 97 + best_half = i; 98 + best_div = j; 99 + goto out; 100 + } 103 101 104 - if (abs(rate - rounded / i) < 105 - abs(rate - best_parent / best_div)) { 106 - best_parent = rounded; 107 - best_div = i; 102 + if (abs(rate - rounded / i) < 103 + abs(rate - best_parent / best_div)) { 104 + best_parent = rounded; 105 + best_div = i; 106 + } 108 107 } 109 108 } 110 109 } 110 + 111 + if (!parent) 112 + return -EINVAL; 111 113 112 114 out: 113 115 req->rate = best_parent / best_half / best_div; ··· 134 124 parent_rate /= 2; 135 125 136 126 reg = readl(tmds->hdmi->base + SUN4I_HDMI_PLL_CTRL_REG); 137 - reg = (reg >> 4) & 0xf; 127 + reg = ((reg >> 4) & 0xf) + tmds->div_offset; 138 128 if (!reg) 139 129 reg = 1; 140 130 ··· 149 139 u32 reg; 150 140 u8 div; 151 141 152 - sun4i_tmds_calc_divider(rate, parent_rate, &div, &half); 142 + sun4i_tmds_calc_divider(rate, parent_rate, tmds->div_offset, 143 + &div, &half); 153 144 154 145 reg = readl(tmds->hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG); 155 146 reg &= ~SUN4I_HDMI_PAD_CTRL1_HALVE_CLK; ··· 160 149 161 150 reg = readl(tmds->hdmi->base + SUN4I_HDMI_PLL_CTRL_REG); 162 151 reg &= ~SUN4I_HDMI_PLL_CTRL_DIV_MASK; 163 - writel(reg | SUN4I_HDMI_PLL_CTRL_DIV(div), 152 + writel(reg | SUN4I_HDMI_PLL_CTRL_DIV(div - tmds->div_offset), 164 153 tmds->hdmi->base + SUN4I_HDMI_PLL_CTRL_REG); 165 154 166 155 return 0; ··· 227 216 228 217 tmds->hdmi = hdmi; 229 218 tmds->hw.init = &init; 219 + tmds->div_offset = hdmi->variant->tmds_clk_div_offset; 230 220 231 221 hdmi->tmds_clk = devm_clk_register(hdmi->dev, &tmds->hw); 232 222 if (IS_ERR(hdmi->tmds_clk))
+74 -17
drivers/gpu/drm/sun4i/sun4i_tcon.c
··· 14 14 #include <drm/drm_atomic_helper.h> 15 15 #include <drm/drm_crtc.h> 16 16 #include <drm/drm_crtc_helper.h> 17 + #include <drm/drm_encoder.h> 17 18 #include <drm/drm_modes.h> 18 19 #include <drm/drm_of.h> 20 + 21 + #include <uapi/drm/drm_mode.h> 19 22 20 23 #include <linux/component.h> 21 24 #include <linux/ioport.h> ··· 112 109 } 113 110 EXPORT_SYMBOL(sun4i_tcon_enable_vblank); 114 111 112 + /* 113 + * This function is a helper for TCON output muxing. The TCON output 114 + * muxing control register in earlier SoCs (without the TCON TOP block) 115 + * are located in TCON0. This helper returns a pointer to TCON0's 116 + * sun4i_tcon structure, or NULL if not found. 117 + */ 118 + static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm) 119 + { 120 + struct sun4i_drv *drv = drm->dev_private; 121 + struct sun4i_tcon *tcon; 122 + 123 + list_for_each_entry(tcon, &drv->tcon_list, list) 124 + if (tcon->id == 0) 125 + return tcon; 126 + 127 + dev_warn(drm->dev, 128 + "TCON0 not found, display output muxing may not work\n"); 129 + 130 + return NULL; 131 + } 132 + 115 133 void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel, 116 134 struct drm_encoder *encoder) 117 135 { 118 - u32 val; 136 + int ret = -ENOTSUPP; 119 137 120 - if (!tcon->quirks->has_unknown_mux) 121 - return; 138 + if (tcon->quirks->set_mux) 139 + ret = tcon->quirks->set_mux(tcon, encoder); 122 140 123 - if (channel != 1) 124 - return; 125 - 126 - if (encoder->encoder_type == DRM_MODE_ENCODER_TVDAC) 127 - val = 1; 128 - else 129 - val = 0; 130 - 131 - /* 132 - * FIXME: Undocumented bits 133 - */ 134 - regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, val); 141 + DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n", 142 + encoder->name, encoder->crtc->name, ret); 135 143 } 136 144 EXPORT_SYMBOL(sun4i_tcon_set_mux); 137 145 ··· 781 767 return 0; 782 768 } 783 769 770 + /* platform specific TCON muxing callbacks */ 771 + static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon, 772 + struct drm_encoder *encoder) 773 + { 774 + u32 val; 775 + 776 + if (encoder->encoder_type == DRM_MODE_ENCODER_TVDAC) 777 + val = 1; 778 + else 779 + val = 0; 780 + 781 + /* 782 + * FIXME: Undocumented bits 783 + */ 784 + return regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, val); 785 + } 786 + 787 + static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon, 788 + struct drm_encoder *encoder) 789 + { 790 + struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev); 791 + u32 shift; 792 + 793 + if (!tcon0) 794 + return -EINVAL; 795 + 796 + switch (encoder->encoder_type) { 797 + case DRM_MODE_ENCODER_TMDS: 798 + /* HDMI */ 799 + shift = 8; 800 + break; 801 + default: 802 + /* TODO A31 has MIPI DSI but A31s does not */ 803 + return -EINVAL; 804 + } 805 + 806 + regmap_update_bits(tcon0->regs, SUN4I_TCON_MUX_CTRL_REG, 807 + 0x3 << shift, tcon->id << shift); 808 + 809 + return 0; 810 + } 811 + 784 812 static const struct sun4i_tcon_quirks sun5i_a13_quirks = { 785 - .has_unknown_mux = true, 786 - .has_channel_1 = true, 813 + .has_channel_1 = true, 814 + .set_mux = sun5i_a13_tcon_set_mux, 787 815 }; 788 816 789 817 static const struct sun4i_tcon_quirks sun6i_a31_quirks = { 790 818 .has_channel_1 = true, 791 819 .needs_de_be_mux = true, 820 + .set_mux = sun6i_tcon_set_mux, 792 821 }; 793 822 794 823 static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
+5 -1
drivers/gpu/drm/sun4i/sun4i_tcon.h
··· 145 145 146 146 #define SUN4I_TCON_MAX_CHANNELS 2 147 147 148 + struct sun4i_tcon; 149 + 148 150 struct sun4i_tcon_quirks { 149 - bool has_unknown_mux; /* sun5i has undocumented mux */ 150 151 bool has_channel_1; /* a33 does not have channel 1 */ 151 152 bool needs_de_be_mux; /* sun6i needs mux to select backend */ 153 + 154 + /* callback to handle tcon muxing options */ 155 + int (*set_mux)(struct sun4i_tcon *, struct drm_encoder *); 152 156 }; 153 157 154 158 struct sun4i_tcon {
+6 -11
drivers/gpu/drm/vc4/vc4_dpi.c
··· 97 97 98 98 struct drm_encoder *encoder; 99 99 struct drm_connector *connector; 100 - struct drm_bridge *bridge; 101 - bool is_panel_bridge; 102 100 103 101 void __iomem *regs; 104 102 ··· 249 251 { 250 252 struct device *dev = &dpi->pdev->dev; 251 253 struct drm_panel *panel; 254 + struct drm_bridge *bridge; 252 255 int ret; 253 256 254 257 ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, 255 - &panel, &dpi->bridge); 258 + &panel, &bridge); 256 259 if (ret) { 257 260 /* If nothing was connected in the DT, that's not an 258 261 * error. ··· 264 265 return ret; 265 266 } 266 267 267 - if (panel) { 268 - dpi->bridge = drm_panel_bridge_add(panel, 269 - DRM_MODE_CONNECTOR_DPI); 270 - dpi->is_panel_bridge = true; 271 - } 268 + if (panel) 269 + bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DPI); 272 270 273 - return drm_bridge_attach(dpi->encoder, dpi->bridge, NULL); 271 + return drm_bridge_attach(dpi->encoder, bridge, NULL); 274 272 } 275 273 276 274 static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) ··· 348 352 struct vc4_dev *vc4 = to_vc4_dev(drm); 349 353 struct vc4_dpi *dpi = dev_get_drvdata(dev); 350 354 351 - if (dpi->is_panel_bridge) 352 - drm_panel_bridge_remove(dpi->bridge); 355 + drm_of_panel_bridge_remove(dev->of_node, 0, 0); 353 356 354 357 drm_encoder_cleanup(dpi->encoder); 355 358
+4
include/drm/bridge/mhl.h
··· 262 262 #define MHL_RAPK_UNSUPPORTED 0x02 /* Rcvd RAP action code not supported */ 263 263 #define MHL_RAPK_BUSY 0x03 /* Responder too busy to respond */ 264 264 265 + /* Bit masks for RCP messages */ 266 + #define MHL_RCP_KEY_RELEASED_MASK 0x80 267 + #define MHL_RCP_KEY_ID_MASK 0x7F 268 + 265 269 /* 266 270 * Error status codes for RCPE messages 267 271 */
+45 -49
include/drm/drm_atomic.h
··· 585 585 */ 586 586 #define for_each_oldnew_connector_in_state(__state, connector, old_connector_state, new_connector_state, __i) \ 587 587 for ((__i) = 0; \ 588 - (__i) < (__state)->num_connector && \ 589 - ((connector) = (__state)->connectors[__i].ptr, \ 590 - (old_connector_state) = (__state)->connectors[__i].old_state, \ 591 - (new_connector_state) = (__state)->connectors[__i].new_state, 1); \ 592 - (__i)++) \ 593 - for_each_if (connector) 588 + (__i) < (__state)->num_connector; \ 589 + (__i)++) \ 590 + for_each_if ((__state)->connectors[__i].ptr && \ 591 + ((connector) = (__state)->connectors[__i].ptr, \ 592 + (old_connector_state) = (__state)->connectors[__i].old_state, \ 593 + (new_connector_state) = (__state)->connectors[__i].new_state, 1)) 594 594 595 595 /** 596 596 * for_each_old_connector_in_state - iterate over all connectors in an atomic update ··· 606 606 */ 607 607 #define for_each_old_connector_in_state(__state, connector, old_connector_state, __i) \ 608 608 for ((__i) = 0; \ 609 - (__i) < (__state)->num_connector && \ 610 - ((connector) = (__state)->connectors[__i].ptr, \ 611 - (old_connector_state) = (__state)->connectors[__i].old_state, 1); \ 612 - (__i)++) \ 613 - for_each_if (connector) 609 + (__i) < (__state)->num_connector; \ 610 + (__i)++) \ 611 + for_each_if ((__state)->connectors[__i].ptr && \ 612 + ((connector) = (__state)->connectors[__i].ptr, \ 613 + (old_connector_state) = (__state)->connectors[__i].old_state, 1)) 614 614 615 615 /** 616 616 * for_each_new_connector_in_state - iterate over all connectors in an atomic update ··· 626 626 */ 627 627 #define for_each_new_connector_in_state(__state, connector, new_connector_state, __i) \ 628 628 for ((__i) = 0; \ 629 - (__i) < (__state)->num_connector && \ 630 - ((connector) = (__state)->connectors[__i].ptr, \ 631 - (new_connector_state) = (__state)->connectors[__i].new_state, 1); \ 632 - (__i)++) \ 633 - for_each_if (connector) 629 + (__i) < (__state)->num_connector; \ 630 + (__i)++) \ 631 + for_each_if ((__state)->connectors[__i].ptr && \ 632 + ((connector) = (__state)->connectors[__i].ptr, \ 633 + (new_connector_state) = (__state)->connectors[__i].new_state, 1)) 634 634 635 635 /** 636 636 * for_each_oldnew_crtc_in_state - iterate over all CRTCs in an atomic update ··· 646 646 */ 647 647 #define for_each_oldnew_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \ 648 648 for ((__i) = 0; \ 649 - (__i) < (__state)->dev->mode_config.num_crtc && \ 650 - ((crtc) = (__state)->crtcs[__i].ptr, \ 651 - (old_crtc_state) = (__state)->crtcs[__i].old_state, \ 652 - (new_crtc_state) = (__state)->crtcs[__i].new_state, 1); \ 649 + (__i) < (__state)->dev->mode_config.num_crtc; \ 653 650 (__i)++) \ 654 - for_each_if (crtc) 651 + for_each_if ((__state)->crtcs[__i].ptr && \ 652 + ((crtc) = (__state)->crtcs[__i].ptr, \ 653 + (old_crtc_state) = (__state)->crtcs[__i].old_state, \ 654 + (new_crtc_state) = (__state)->crtcs[__i].new_state, 1)) 655 655 656 656 /** 657 657 * for_each_old_crtc_in_state - iterate over all CRTCs in an atomic update ··· 666 666 */ 667 667 #define for_each_old_crtc_in_state(__state, crtc, old_crtc_state, __i) \ 668 668 for ((__i) = 0; \ 669 - (__i) < (__state)->dev->mode_config.num_crtc && \ 670 - ((crtc) = (__state)->crtcs[__i].ptr, \ 671 - (old_crtc_state) = (__state)->crtcs[__i].old_state, 1); \ 669 + (__i) < (__state)->dev->mode_config.num_crtc; \ 672 670 (__i)++) \ 673 - for_each_if (crtc) 671 + for_each_if ((__state)->crtcs[__i].ptr && \ 672 + ((crtc) = (__state)->crtcs[__i].ptr, \ 673 + (old_crtc_state) = (__state)->crtcs[__i].old_state, 1)) 674 674 675 675 /** 676 676 * for_each_new_crtc_in_state - iterate over all CRTCs in an atomic update ··· 685 685 */ 686 686 #define for_each_new_crtc_in_state(__state, crtc, new_crtc_state, __i) \ 687 687 for ((__i) = 0; \ 688 - (__i) < (__state)->dev->mode_config.num_crtc && \ 689 - ((crtc) = (__state)->crtcs[__i].ptr, \ 690 - (new_crtc_state) = (__state)->crtcs[__i].new_state, 1); \ 688 + (__i) < (__state)->dev->mode_config.num_crtc; \ 691 689 (__i)++) \ 692 - for_each_if (crtc) 690 + for_each_if ((__state)->crtcs[__i].ptr && \ 691 + ((crtc) = (__state)->crtcs[__i].ptr, \ 692 + (new_crtc_state) = (__state)->crtcs[__i].new_state, 1)) 693 693 694 694 /** 695 695 * for_each_oldnew_plane_in_state - iterate over all planes in an atomic update ··· 705 705 */ 706 706 #define for_each_oldnew_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \ 707 707 for ((__i) = 0; \ 708 - (__i) < (__state)->dev->mode_config.num_total_plane && \ 709 - ((plane) = (__state)->planes[__i].ptr, \ 710 - (old_plane_state) = (__state)->planes[__i].old_state, \ 711 - (new_plane_state) = (__state)->planes[__i].new_state, 1); \ 708 + (__i) < (__state)->dev->mode_config.num_total_plane; \ 712 709 (__i)++) \ 713 - for_each_if (plane) 710 + for_each_if ((__state)->planes[__i].ptr && \ 711 + ((plane) = (__state)->planes[__i].ptr, \ 712 + (old_plane_state) = (__state)->planes[__i].old_state,\ 713 + (new_plane_state) = (__state)->planes[__i].new_state, 1)) 714 714 715 715 /** 716 716 * for_each_old_plane_in_state - iterate over all planes in an atomic update ··· 725 725 */ 726 726 #define for_each_old_plane_in_state(__state, plane, old_plane_state, __i) \ 727 727 for ((__i) = 0; \ 728 - (__i) < (__state)->dev->mode_config.num_total_plane && \ 729 - ((plane) = (__state)->planes[__i].ptr, \ 730 - (old_plane_state) = (__state)->planes[__i].old_state, 1); \ 728 + (__i) < (__state)->dev->mode_config.num_total_plane; \ 731 729 (__i)++) \ 732 - for_each_if (plane) 733 - 730 + for_each_if ((__state)->planes[__i].ptr && \ 731 + ((plane) = (__state)->planes[__i].ptr, \ 732 + (old_plane_state) = (__state)->planes[__i].old_state, 1)) 734 733 /** 735 734 * for_each_new_plane_in_state - iterate over all planes in an atomic update 736 735 * @__state: &struct drm_atomic_state pointer ··· 743 744 */ 744 745 #define for_each_new_plane_in_state(__state, plane, new_plane_state, __i) \ 745 746 for ((__i) = 0; \ 746 - (__i) < (__state)->dev->mode_config.num_total_plane && \ 747 - ((plane) = (__state)->planes[__i].ptr, \ 748 - (new_plane_state) = (__state)->planes[__i].new_state, 1); \ 747 + (__i) < (__state)->dev->mode_config.num_total_plane; \ 749 748 (__i)++) \ 750 - for_each_if (plane) 749 + for_each_if ((__state)->planes[__i].ptr && \ 750 + ((plane) = (__state)->planes[__i].ptr, \ 751 + (new_plane_state) = (__state)->planes[__i].new_state, 1)) 751 752 752 753 /** 753 754 * for_each_oldnew_private_obj_in_state - iterate over all private objects in an atomic update ··· 767 768 ((obj) = (__state)->private_objs[__i].ptr, \ 768 769 (old_obj_state) = (__state)->private_objs[__i].old_state, \ 769 770 (new_obj_state) = (__state)->private_objs[__i].new_state, 1); \ 770 - (__i)++) \ 771 - for_each_if (obj) 771 + (__i)++) 772 772 773 773 /** 774 774 * for_each_old_private_obj_in_state - iterate over all private objects in an atomic update ··· 785 787 (__i) < (__state)->num_private_objs && \ 786 788 ((obj) = (__state)->private_objs[__i].ptr, \ 787 789 (old_obj_state) = (__state)->private_objs[__i].old_state, 1); \ 788 - (__i)++) \ 789 - for_each_if (obj) 790 + (__i)++) 790 791 791 792 /** 792 793 * for_each_new_private_obj_in_state - iterate over all private objects in an atomic update ··· 803 806 (__i) < (__state)->num_private_objs && \ 804 807 ((obj) = (__state)->private_objs[__i].ptr, \ 805 808 (new_obj_state) = (__state)->private_objs[__i].new_state, 1); \ 806 - (__i)++) \ 807 - for_each_if (obj) 809 + (__i)++) 808 810 809 811 /** 810 812 * drm_atomic_crtc_needs_modeset - compute combined modeset need
+8
include/drm/drm_of.h
··· 29 29 int port, int endpoint, 30 30 struct drm_panel **panel, 31 31 struct drm_bridge **bridge); 32 + int drm_of_panel_bridge_remove(const struct device_node *np, 33 + int port, int endpoint); 32 34 #else 33 35 static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, 34 36 struct device_node *port) ··· 64 62 int port, int endpoint, 65 63 struct drm_panel **panel, 66 64 struct drm_bridge **bridge) 65 + { 66 + return -EINVAL; 67 + } 68 + 69 + static inline int drm_of_panel_bridge_remove(const struct device_node *np, 70 + int port, int endpoint) 67 71 { 68 72 return -EINVAL; 69 73 }
+4 -1
include/linux/dma-fence.h
··· 248 248 struct dma_fence *fence; 249 249 250 250 fence = rcu_dereference(*fencep); 251 - if (!fence || !dma_fence_get_rcu(fence)) 251 + if (!fence) 252 252 return NULL; 253 + 254 + if (!dma_fence_get_rcu(fence)) 255 + continue; 253 256 254 257 /* The atomic_inc_not_zero() inside dma_fence_get_rcu() 255 258 * provides a full memory barrier upon success (such as now).
+39
include/linux/regmap.h
··· 139 139 pollret ?: ((cond) ? 0 : -ETIMEDOUT); \ 140 140 }) 141 141 142 + /** 143 + * regmap_field_read_poll_timeout - Poll until a condition is met or timeout 144 + * 145 + * @field: Regmap field to read from 146 + * @val: Unsigned integer variable to read the value into 147 + * @cond: Break condition (usually involving @val) 148 + * @sleep_us: Maximum time to sleep between reads in us (0 149 + * tight-loops). Should be less than ~20ms since usleep_range 150 + * is used (see Documentation/timers/timers-howto.txt). 151 + * @timeout_us: Timeout in us, 0 means never timeout 152 + * 153 + * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_field_read 154 + * error return value in case of a error read. In the two former cases, 155 + * the last read value at @addr is stored in @val. Must not be called 156 + * from atomic context if sleep_us or timeout_us are used. 157 + * 158 + * This is modelled after the readx_poll_timeout macros in linux/iopoll.h. 159 + */ 160 + #define regmap_field_read_poll_timeout(field, val, cond, sleep_us, timeout_us) \ 161 + ({ \ 162 + ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \ 163 + int pollret; \ 164 + might_sleep_if(sleep_us); \ 165 + for (;;) { \ 166 + pollret = regmap_field_read((field), &(val)); \ 167 + if (pollret) \ 168 + break; \ 169 + if (cond) \ 170 + break; \ 171 + if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \ 172 + pollret = regmap_field_read((field), &(val)); \ 173 + break; \ 174 + } \ 175 + if (sleep_us) \ 176 + usleep_range((sleep_us >> 2) + 1, sleep_us); \ 177 + } \ 178 + pollret ?: ((cond) ? 0 : -ETIMEDOUT); \ 179 + }) 180 + 142 181 #ifdef CONFIG_REGMAP 143 182 144 183 enum regmap_endian {