diff options
170 files changed, 3525 insertions, 1860 deletions
diff --git a/Documentation/devicetree/bindings/media/i2c/adv7180.txt b/Documentation/devicetree/bindings/media/i2c/adv7180.txt index 4da486f96ff6..552b6a82cb1f 100644 --- a/Documentation/devicetree/bindings/media/i2c/adv7180.txt +++ b/Documentation/devicetree/bindings/media/i2c/adv7180.txt @@ -6,6 +6,8 @@ digital interfaces like MIPI CSI-2 or parallel video. Required Properties : - compatible : value must be one of "adi,adv7180" + "adi,adv7180cp" + "adi,adv7180st" "adi,adv7182" "adi,adv7280" "adi,adv7280-m" @@ -15,6 +17,19 @@ Required Properties : "adi,adv7282" "adi,adv7282-m" +Device nodes of "adi,adv7180cp" and "adi,adv7180st" must contain one +'port' child node per device input and output port, in accordance with the +video interface bindings defined in +Documentation/devicetree/bindings/media/video-interfaces.txt. The port +nodes are numbered as follows. + + Port adv7180cp adv7180st +------------------------------------------------------------------- + Input 0-2 0-5 + Output 3 6 + +The digital output port node must contain at least one endpoint. + Optional Properties : - powerdown-gpios: reference to the GPIO connected to the powerdown pin, if any. diff --git a/Documentation/devicetree/bindings/media/st,stm32-dcmi.txt b/Documentation/devicetree/bindings/media/st,stm32-dcmi.txt new file mode 100644 index 000000000000..249790a93017 --- /dev/null +++ b/Documentation/devicetree/bindings/media/st,stm32-dcmi.txt @@ -0,0 +1,45 @@ +STMicroelectronics STM32 Digital Camera Memory Interface (DCMI) + +Required properties: +- compatible: "st,stm32-dcmi" +- reg: physical base address and length of the registers set for the device +- interrupts: should contain IRQ line for the DCMI +- resets: reference to a reset controller, + see Documentation/devicetree/bindings/reset/st,stm32-rcc.txt +- clocks: list of clock specifiers, corresponding to entries in + the clock-names property +- clock-names: must contain "mclk", which is the DCMI peripherial clock +- pinctrl: the pincontrol settings to configure muxing properly + for pins that connect to DCMI device. + See Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt. +- dmas: phandle to DMA controller node, + see Documentation/devicetree/bindings/dma/stm32-dma.txt +- dma-names: must contain "tx", which is the transmit channel from DCMI to DMA + +DCMI supports a single port node with parallel bus. It should contain one +'port' child node with child 'endpoint' node. Please refer to the bindings +defined in Documentation/devicetree/bindings/media/video-interfaces.txt. + +Example: + + dcmi: dcmi@50050000 { + compatible = "st,stm32-dcmi"; + reg = <0x50050000 0x400>; + interrupts = <78>; + resets = <&rcc STM32F4_AHB2_RESET(DCMI)>; + clocks = <&rcc 0 STM32F4_AHB2_CLOCK(DCMI)>; + clock-names = "mclk"; + pinctrl-names = "default"; + pinctrl-0 = <&dcmi_pins>; + dmas = <&dma2 1 1 0x414 0x3>; + dma-names = "tx"; + port { + dcmi_0: endpoint { + remote-endpoint = <...>; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; + pclk-sample = <1>; + }; + }; + }; diff --git a/Documentation/media/kapi/v4l2-core.rst b/Documentation/media/kapi/v4l2-core.rst index d8f6c46d26d5..c7434f38fd9c 100644 --- a/Documentation/media/kapi/v4l2-core.rst +++ b/Documentation/media/kapi/v4l2-core.rst @@ -19,7 +19,7 @@ Video4Linux devices v4l2-mc v4l2-mediabus v4l2-mem2mem - v4l2-of + v4l2-fwnode v4l2-rect v4l2-tuner v4l2-common diff --git a/Documentation/media/kapi/v4l2-fwnode.rst b/Documentation/media/kapi/v4l2-fwnode.rst new file mode 100644 index 000000000000..6c8bccdfeb25 --- /dev/null +++ b/Documentation/media/kapi/v4l2-fwnode.rst @@ -0,0 +1,3 @@ +V4L2 fwnode kAPI +^^^^^^^^^^^^^^^^ +.. kernel-doc:: include/media/v4l2-fwnode.h diff --git a/Documentation/media/kapi/v4l2-of.rst b/Documentation/media/kapi/v4l2-of.rst deleted file mode 100644 index 1ddf76b00944..000000000000 --- a/Documentation/media/kapi/v4l2-of.rst +++ /dev/null @@ -1,3 +0,0 @@ -V4L2 Open Firmware kAPI -^^^^^^^^^^^^^^^^^^^^^^^ -.. kernel-doc:: include/media/v4l2-of.h diff --git a/Documentation/media/uapi/v4l/extended-controls.rst b/Documentation/media/uapi/v4l/extended-controls.rst index abb105724c05..76c5b1aeaadd 100644 --- a/Documentation/media/uapi/v4l/extended-controls.rst +++ b/Documentation/media/uapi/v4l/extended-controls.rst @@ -2019,7 +2019,7 @@ enum v4l2_exposure_auto_type - dynamically vary the frame rate. By default this feature is disabled (0) and the frame rate must remain constant. -``V4L2_CID_EXPOSURE_BIAS (integer menu)`` +``V4L2_CID_AUTO_EXPOSURE_BIAS (integer menu)`` Determines the automatic exposure compensation, it is effective only when ``V4L2_CID_EXPOSURE_AUTO`` control is set to ``AUTO``, ``SHUTTER_PRIORITY`` or ``APERTURE_PRIORITY``. It is expressed in diff --git a/drivers/leds/leds-aat1290.c b/drivers/leds/leds-aat1290.c index def3cf9f7e92..a21e19297745 100644 --- a/drivers/leds/leds-aat1290.c +++ b/drivers/leds/leds-aat1290.c @@ -503,8 +503,9 @@ static int aat1290_led_probe(struct platform_device *pdev) aat1290_init_v4l2_flash_config(led, &led_cfg, &v4l2_sd_cfg); /* Create V4L2 Flash subdev. */ - led->v4l2_flash = v4l2_flash_init(dev, sub_node, fled_cdev, NULL, - &v4l2_flash_ops, &v4l2_sd_cfg); + led->v4l2_flash = v4l2_flash_init(dev, of_fwnode_handle(sub_node), + fled_cdev, NULL, &v4l2_flash_ops, + &v4l2_sd_cfg); if (IS_ERR(led->v4l2_flash)) { ret = PTR_ERR(led->v4l2_flash); goto error_v4l2_flash_init; diff --git a/drivers/leds/leds-max77693.c b/drivers/leds/leds-max77693.c index 1eb58ef6aefe..2d3062d53325 100644 --- a/drivers/leds/leds-max77693.c +++ b/drivers/leds/leds-max77693.c @@ -930,8 +930,9 @@ static int max77693_register_led(struct max77693_sub_led *sub_led, max77693_init_v4l2_flash_config(sub_led, led_cfg, &v4l2_sd_cfg); /* Register in the V4L2 subsystem. */ - sub_led->v4l2_flash = v4l2_flash_init(dev, sub_node, fled_cdev, NULL, - &v4l2_flash_ops, &v4l2_sd_cfg); + sub_led->v4l2_flash = v4l2_flash_init(dev, of_fwnode_handle(sub_node), + fled_cdev, NULL, &v4l2_flash_ops, + &v4l2_sd_cfg); if (IS_ERR(sub_led->v4l2_flash)) { ret = PTR_ERR(sub_led->v4l2_flash); goto err_v4l2_flash_init; diff --git a/drivers/media/cec/Kconfig b/drivers/media/cec/Kconfig index 4e25a950ae6f..43428cec3a01 100644 --- a/drivers/media/cec/Kconfig +++ b/drivers/media/cec/Kconfig @@ -1,5 +1,6 @@ config MEDIA_CEC_RC bool "HDMI CEC RC integration" depends on CEC_CORE && RC_CORE + depends on CEC_CORE=m || RC_CORE=y ---help--- Pass on CEC remote control messages to the RC framework. diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c index b978002af4d8..51f942fc0669 100644 --- a/drivers/media/dvb-frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c @@ -535,6 +535,7 @@ static void af9013_statistics_work(struct work_struct *work) switch (state->statistics_step) { default: state->statistics_step = 0; + /* fall-through */ case 0: af9013_statistics_signal_strength(&state->fe); state->statistics_step++; diff --git a/drivers/media/dvb-frontends/au8522_common.c b/drivers/media/dvb-frontends/au8522_common.c index cf4ac240a01f..6722838c3707 100644 --- a/drivers/media/dvb-frontends/au8522_common.c +++ b/drivers/media/dvb-frontends/au8522_common.c @@ -234,6 +234,7 @@ int au8522_init(struct dvb_frontend *fe) chip, so that when it gets powered back up it won't think that it is already tuned */ state->current_frequency = 0; + state->current_modulation = VSB_8; au8522_writereg(state, 0xa4, 1 << 5); diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c index a2e771305008..343dc92ef54e 100644 --- a/drivers/media/dvb-frontends/au8522_decoder.c +++ b/drivers/media/dvb-frontends/au8522_decoder.c @@ -17,7 +17,6 @@ /* Developer notes: * - * VBI support is not yet working * Enough is implemented here for CVBS and S-Video inputs, but the actual * analog demodulator code isn't implemented (not needed for xc5000 since it * has its own demodulator and outputs CVBS) @@ -179,42 +178,6 @@ static inline struct au8522_state *to_state(struct v4l2_subdev *sd) return container_of(sd, struct au8522_state, sd); } -static void setup_vbi(struct au8522_state *state, int aud_input) -{ - int i; - - /* These are set to zero regardless of what mode we're in */ - au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_L_REG018H, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_THRESH1_REG01CH, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H, - 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H, - 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H, - 0x00); - - /* Setup the VBI registers */ - for (i = 0x30; i < 0x60; i++) - au8522_writereg(state, i, 0x40); - - /* For some reason, every register is 0x40 except register 0x44 - (confirmed via the HVR-950q USB capture) */ - au8522_writereg(state, 0x44, 0x60); - - /* Enable VBI (we always do this regardless of whether the user is - viewing closed caption info) */ - au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, - AU8522_TVDEC_VBI_CTRL_H_REG017H_CCON); - -} - static void setup_decoder_defaults(struct au8522_state *state, bool is_svideo) { int i; @@ -317,8 +280,6 @@ static void setup_decoder_defaults(struct au8522_state *state, bool is_svideo) AU8522_TOREGAAGC_REG0E5H_CVBS); au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS); - setup_vbi(state, 0); - if (is_svideo) { /* Despite what the table says, for the HVR-950q we still need to be in CVBS mode for the S-Video input (reason unknown). */ @@ -456,30 +417,29 @@ static void set_audio_input(struct au8522_state *state) lpfilter_coef[i].reg_val[0]); } - /* Setup audio */ - au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00); - au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00); - au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00); - au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80); - au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84); - msleep(150); - au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00); - msleep(10); - au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, - AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); - msleep(50); + /* Set the volume */ au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F); au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F); au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0xff); - msleep(80); - au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F); - au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F); + + /* Not sure what this does */ au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO); + + /* Setup the audio mode to stereo DBX */ au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x82); msleep(70); - au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x09); + + /* Start the audio processing module */ + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d); + + /* Set the audio frequency to 48 KHz */ au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03); + + /* Set the I2S parameters (WS, LSB, mode, sample rate */ au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0xc2); + + /* Enable the I2S output */ + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x09); } /* ----------------------------------------------------------------------- */ @@ -663,10 +623,12 @@ static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) int val = 0; struct au8522_state *state = to_state(sd); u8 lock_status; + u8 pll_status; /* Interrogate the decoder to see if we are getting a real signal */ lock_status = au8522_readreg(state, 0x00); - if (lock_status == 0xa2) + pll_status = au8522_readreg(state, 0x7e); + if ((lock_status == 0xa2) && (pll_status & 0x10)) vt->signal = 0xffff; else vt->signal = 0x00; diff --git a/drivers/media/dvb-frontends/au8522_dig.c b/drivers/media/dvb-frontends/au8522_dig.c index 7ed326e43fc4..3f3635f5a06a 100644 --- a/drivers/media/dvb-frontends/au8522_dig.c +++ b/drivers/media/dvb-frontends/au8522_dig.c @@ -271,9 +271,9 @@ static int au8522_set_if(struct dvb_frontend *fe, enum au8522_if_freq if_freq) return -EINVAL; } dprintk("%s() %s MHz\n", __func__, ifmhz); - au8522_writereg(state, 0x80b5, r0b5); - au8522_writereg(state, 0x80b6, r0b6); - au8522_writereg(state, 0x80b7, r0b7); + au8522_writereg(state, 0x00b5, r0b5); + au8522_writereg(state, 0x00b6, r0b6); + au8522_writereg(state, 0x00b7, r0b7); return 0; } @@ -283,33 +283,32 @@ static struct { u16 reg; u16 data; } VSB_mod_tab[] = { - { 0x8090, 0x84 }, - { 0x4092, 0x11 }, + { 0x0090, 0x84 }, { 0x2005, 0x00 }, - { 0x8091, 0x80 }, - { 0x80a3, 0x0c }, - { 0x80a4, 0xe8 }, - { 0x8081, 0xc4 }, - { 0x80a5, 0x40 }, - { 0x80a7, 0x40 }, - { 0x80a6, 0x67 }, - { 0x8262, 0x20 }, - { 0x821c, 0x30 }, - { 0x80d8, 0x1a }, - { 0x8227, 0xa0 }, - { 0x8121, 0xff }, - { 0x80a8, 0xf0 }, - { 0x80a9, 0x05 }, - { 0x80aa, 0x77 }, - { 0x80ab, 0xf0 }, - { 0x80ac, 0x05 }, - { 0x80ad, 0x77 }, - { 0x80ae, 0x41 }, - { 0x80af, 0x66 }, - { 0x821b, 0xcc }, - { 0x821d, 0x80 }, - { 0x80a4, 0xe8 }, - { 0x8231, 0x13 }, + { 0x0091, 0x80 }, + { 0x00a3, 0x0c }, + { 0x00a4, 0xe8 }, + { 0x0081, 0xc4 }, + { 0x00a5, 0x40 }, + { 0x00a7, 0x40 }, + { 0x00a6, 0x67 }, + { 0x0262, 0x20 }, + { 0x021c, 0x30 }, + { 0x00d8, 0x1a }, + { 0x0227, 0xa0 }, + { 0x0121, 0xff }, + { 0x00a8, 0xf0 }, + { 0x00a9, 0x05 }, + { 0x00aa, 0x77 }, + { 0x00ab, 0xf0 }, + { 0x00ac, 0x05 }, + { 0x00ad, 0x77 }, + { 0x00ae, 0x41 }, + { 0x00af, 0x66 }, + { 0x021b, 0xcc }, + { 0x021d, 0x80 }, + { 0x00a4, 0xe8 }, + { 0x0231, 0x13 }, }; /* QAM64 Modulation table */ @@ -396,78 +395,78 @@ static struct { u16 reg; u16 data; } QAM256_mod_tab[] = { - { 0x80a3, 0x09 }, - { 0x80a4, 0x00 }, - { 0x8081, 0xc4 }, - { 0x80a5, 0x40 }, - { 0x80aa, 0x77 }, - { 0x80ad, 0x77 }, - { 0x80a6, 0x67 }, - { 0x8262, 0x20 }, - { 0x821c, 0x30 }, - { 0x80b8, 0x3e }, - { 0x80b9, 0xf0 }, - { 0x80ba, 0x01 }, - { 0x80bb, 0x18 }, - { 0x80bc, 0x50 }, - { 0x80bd, 0x00 }, - { 0x80be, 0xea }, - { 0x80bf, 0xef }, - { 0x80c0, 0xfc }, - { 0x80c1, 0xbd }, - { 0x80c2, 0x1f }, - { 0x80c3, 0xfc }, - { 0x80c4, 0xdd }, - { 0x80c5, 0xaf }, - { 0x80c6, 0x00 }, - { 0x80c7, 0x38 }, - { 0x80c8, 0x30 }, - { 0x80c9, 0x05 }, - { 0x80ca, 0x4a }, - { 0x80cb, 0xd0 }, - { 0x80cc, 0x01 }, - { 0x80cd, 0xd9 }, - { 0x80ce, 0x6f }, - { 0x80cf, 0xf9 }, - { 0x80d0, 0x70 }, - { 0x80d1, 0xdf }, - { 0x80d2, 0xf7 }, - { 0x80d3, 0xc2 }, - { 0x80d4, 0xdf }, - { 0x80d5, 0x02 }, - { 0x80d6, 0x9a }, - { 0x80d7, 0xd0 }, - { 0x8250, 0x0d }, - { 0x8251, 0xcd }, - { 0x8252, 0xe0 }, - { 0x8253, 0x05 }, - { 0x8254, 0xa7 }, - { 0x8255, 0xff }, - { 0x8256, 0xed }, - { 0x8257, 0x5b }, - { 0x8258, 0xae }, - { 0x8259, 0xe6 }, - { 0x825a, 0x3d }, - { 0x825b, 0x0f }, - { 0x825c, 0x0d }, - { 0x825d, 0xea }, - { 0x825e, 0xf2 }, - { 0x825f, 0x51 }, - { 0x8260, 0xf5 }, - { 0x8261, 0x06 }, - { 0x821a, 0x00 }, - { 0x8546, 0x40 }, - { 0x8210, 0x26 }, - { 0x8211, 0xf6 }, - { 0x8212, 0x84 }, - { 0x8213, 0x02 }, - { 0x8502, 0x01 }, - { 0x8121, 0x04 }, - { 0x8122, 0x04 }, - { 0x852e, 0x10 }, - { 0x80a4, 0xca }, - { 0x80a7, 0x40 }, - { 0x8526, 0x01 }, + { 0x00a3, 0x09 }, + { 0x00a4, 0x00 }, + { 0x0081, 0xc4 }, + { 0x00a5, 0x40 }, + { 0x00aa, 0x77 }, + { 0x00ad, 0x77 }, + { 0x00a6, 0x67 }, + { 0x0262, 0x20 }, + { 0x021c, 0x30 }, + { 0x00b8, 0x3e }, + { 0x00b9, 0xf0 }, + { 0x00ba, 0x01 }, + { 0x00bb, 0x18 }, + { 0x00bc, 0x50 }, + { 0x00bd, 0x00 }, + { 0x00be, 0xea }, + { 0x00bf, 0xef }, + { 0x00c0, 0xfc }, + { 0x00c1, 0xbd }, + { 0x00c2, 0x1f }, + { 0x00c3, 0xfc }, + { 0x00c4, 0xdd }, + { 0x00c5, 0xaf }, + { 0x00c6, 0x00 }, + { 0x00c7, 0x38 }, + { 0x00c8, 0x30 }, + { 0x00c9, 0x05 }, + { 0x00ca, 0x4a }, + { 0x00cb, 0xd0 }, + { 0x00cc, 0x01 }, + { 0x00cd, 0xd9 }, + { 0x00ce, 0x6f }, + { 0x00cf, 0xf9 }, + { 0x00d0, 0x70 }, + { 0x00d1, 0xdf }, + { 0x00d2, 0xf7 }, + { 0x00d3, 0xc2 }, + { 0x00d4, 0xdf }, + { 0x00d5, 0x02 }, + { 0x00d6, 0x9a }, + { 0x00d7, 0xd0 }, + { 0x0250, 0x0d }, + { 0x0251, 0xcd }, + { 0x0252, 0xe0 }, + { 0x0253, 0x05 }, + { 0x0254, 0xa7 }, + { 0x0255, 0xff }, + { 0x0256, 0xed }, + { 0x0257, 0x5b }, + { 0x0258, 0xae }, + { 0x0259, 0xe6 }, + { 0x025a, 0x3d }, + { 0x025b, 0x0f }, + { 0x025c, 0x0d }, + { 0x025d, 0xea }, + { 0x025e, 0xf2 }, + { 0x025f, 0x51 }, + { 0x0260, 0xf5 }, + { 0x0261, 0x06 }, + { 0x021a, 0x00 }, + { 0x0546, 0x40 }, + { 0x0210, 0x26 }, + { 0x0211, 0xf6 }, + { 0x0212, 0x84 }, + { 0x0213, 0x02 }, + { 0x0502, 0x01 }, + { 0x0121, 0x04 }, + { 0x0122, 0x04 }, + { 0x052e, 0x10 }, + { 0x00a4, 0xca }, + { 0x00a7, 0x40 }, + { 0x0526, 0x01 }, }; static struct { @@ -654,12 +653,12 @@ static int au8522_read_status(struct dvb_frontend *fe, enum fe_status *status) if (state->current_modulation == VSB_8) { dprintk("%s() Checking VSB_8\n", __func__); - reg = au8522_readreg(state, 0x4088); + reg = au8522_readreg(state, 0x0088); if ((reg & 0x03) == 0x03) *status |= FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI; } else { dprintk("%s() Checking QAM\n", __func__); - reg = au8522_readreg(state, 0x4541); + reg = au8522_readreg(state, 0x0541); if (reg & 0x80) *status |= FE_HAS_VITERBI; if (reg & 0x20) @@ -745,17 +744,17 @@ static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr) if (state->current_modulation == QAM_256) ret = au8522_mse2snr_lookup(qam256_mse2snr_tab, ARRAY_SIZE(qam256_mse2snr_tab), - au8522_readreg(state, 0x4522), + au8522_readreg(state, 0x0522), snr); else if (state->current_modulation == QAM_64) ret = au8522_mse2snr_lookup(qam64_mse2snr_tab, ARRAY_SIZE(qam64_mse2snr_tab), - au8522_readreg(state, 0x4522), + au8522_readreg(state, 0x0522), snr); else /* VSB_8 */ ret = au8522_mse2snr_lookup(vsb_mse2snr_tab, ARRAY_SIZE(vsb_mse2snr_tab), - au8522_readreg(state, 0x4311), + au8522_readreg(state, 0x0311), snr); if (state->config.led_cfg) @@ -804,9 +803,9 @@ static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) struct au8522_state *state = fe->demodulator_priv; if (state->current_modulation == VSB_8) - *ucblocks = au8522_readreg(state, 0x4087); + *ucblocks = au8522_readreg(state, 0x0087); else - *ucblocks = au8522_readreg(state, 0x4543); + *ucblocks = au8522_readreg(state, 0x0543); return 0; } diff --git a/drivers/media/dvb-frontends/bcm3510.c b/drivers/media/dvb-frontends/bcm3510.c index 617c5e29f919..ba63ad170d3c 100644 --- a/drivers/media/dvb-frontends/bcm3510.c +++ b/drivers/media/dvb-frontends/bcm3510.c @@ -538,6 +538,7 @@ static int bcm3510_set_frontend(struct dvb_frontend *fe) cmd.ACQUIRE0.MODE = 0x9; cmd.ACQUIRE1.SYM_RATE = 0x0; cmd.ACQUIRE1.IF_FREQ = 0x0; + break; default: return -EINVAL; } @@ -772,7 +773,8 @@ static int bcm3510_init(struct dvb_frontend* fe) deb_info("attempting to download firmware\n"); if ((ret = bcm3510_init_cold(st)) < 0) return ret; - case JDEC_EEPROM_LOAD_WAIT: /* fall-through is wanted */ + /* fall-through */ + case JDEC_EEPROM_LOAD_WAIT: deb_info("firmware is loaded\n"); bcm3510_check_firmware_version(st); break; diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index 3815ea515364..1caa04d8f60f 100644 --- a/drivers/media/dvb-frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c @@ -279,10 +279,10 @@ static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_p if (state->version != SOC7090) reg_1280 &= ~((1 << 11)); reg_1280 &= ~(1 << 6); - /* fall through wanted to enable the interfaces */ - + /* fall-through */ + case DIB7000P_POWER_INTERFACE_ONLY: /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */ - case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */ + /* TODO power up either SDIO or I2C */ if (state->version == SOC7090) reg_1280 &= ~((1 << 7) | (1 << 5)); else diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c index daeaf965dd56..14040c915dbb 100644 --- a/drivers/media/dvb-frontends/drx39xyj/drxj.c +++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c @@ -2837,7 +2837,8 @@ ctrl_set_cfg_mpeg_output(struct drx_demod_instance *demod, struct drx_cfg_mpeg_o /* coef = 188/204 */ max_bit_rate = (ext_attr->curr_symbol_rate / 8) * nr_bits * 188; - /* pass through b/c Annex A/c need following settings */ + /* pass through as b/c Annex A/c need following settings */ + /* fall-through */ case DRX_STANDARD_ITU_B: rc = drxj_dap_write_reg16(dev_addr, FEC_OC_FCT_USAGE__A, FEC_OC_FCT_USAGE__PRE, 0); if (rc != 0) { @@ -4776,9 +4777,9 @@ set_frequency(struct drx_demod_instance *demod, No need to account for mirroring on RF */ switch (ext_attr->standard) { - case DRX_STANDARD_ITU_A: /* fallthrough */ - case DRX_STANDARD_ITU_C: /* fallthrough */ - case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */ + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_C: + case DRX_STANDARD_PAL_SECAM_LP: case DRX_STANDARD_8VSB: select_pos_image = true; break; @@ -4787,11 +4788,12 @@ set_frequency(struct drx_demod_instance *demod, Sound carrier is already 3Mhz above centre frequency due to tuner setting so now add an extra shift of 1MHz... */ fm_frequency_shift = 1000; - case DRX_STANDARD_ITU_B: /* fallthrough */ - case DRX_STANDARD_NTSC: /* fallthrough */ - case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */ - case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */ - case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */ + /*fall through */ + case DRX_STANDARD_ITU_B: + case DRX_STANDARD_NTSC: + case DRX_STANDARD_PAL_SECAM_BG: + case DRX_STANDARD_PAL_SECAM_DK: + case DRX_STANDARD_PAL_SECAM_I: case DRX_STANDARD_PAL_SECAM_L: select_pos_image = false; break; diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c index 71910561005f..17638e08835a 100644 --- a/drivers/media/dvb-frontends/drxd_hard.c +++ b/drivers/media/dvb-frontends/drxd_hard.c @@ -1517,12 +1517,14 @@ static int SetDeviceTypeId(struct drxd_state *state) switch (deviceId) { case 4: state->diversity = 1; + /* fall through */ case 3: case 7: state->PGA = 1; break; case 6: state->diversity = 1; + /* fall through */ case 5: case 8: break; @@ -1969,7 +1971,8 @@ static int DRX_Start(struct drxd_state *state, s32 off) switch (p->transmission_mode) { default: /* Not set, detect it automatically */ operationMode |= SC_RA_RAM_OP_AUTO_MODE__M; - /* fall through , try first guess DRX_FFTMODE_8K */ + /* try first guess DRX_FFTMODE_8K */ + /* fall through */ case TRANSMISSION_MODE_8K: transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_8K; if (state->type_A) { @@ -2143,8 +2146,8 @@ static int DRX_Start(struct drxd_state *state, s32 off) switch (p->modulation) { default: operationMode |= SC_RA_RAM_OP_AUTO_CONST__M; - /* fall through , try first guess - DRX_CONSTELLATION_QAM64 */ + /* try first guess DRX_CONSTELLATION_QAM64 */ + /* fall through */ case QAM_64: transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM64; if (state->type_A) { @@ -2280,6 +2283,7 @@ static int DRX_Start(struct drxd_state *state, s32 off) break; default: operationMode |= SC_RA_RAM_OP_AUTO_RATE__M; + /* fall through */ case FEC_2_3: transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_2_3; if (state->type_A) { diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index 050fe34342d3..48a8aad47a74 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -3271,10 +3271,12 @@ static int dvbt_sc_command(struct drxk_state *state, case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM: status |= write16(state, OFDM_SC_RA_RAM_PARAM1__A, param1); /* All commands using 1 parameters */ + /* fall through */ case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING: case OFDM_SC_RA_RAM_CMD_USER_IO: status |= write16(state, OFDM_SC_RA_RAM_PARAM0__A, param0); /* All commands using 0 parameters */ + /* fall through */ case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM: case OFDM_SC_RA_RAM_CMD_NULL: /* Write command */ @@ -3782,7 +3784,8 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, case TRANSMISSION_MODE_AUTO: default: operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M; - /* fall through , try first guess DRX_FFTMODE_8K */ + /* try first guess DRX_FFTMODE_8K */ + /* fall through */ case TRANSMISSION_MODE_8K: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K; break; @@ -3796,7 +3799,8 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, default: case GUARD_INTERVAL_AUTO: operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M; - /* fall through , try first guess DRX_GUARD_1DIV4 */ + /* try first guess DRX_GUARD_1DIV4 */ + /* fall through */ case GUARD_INTERVAL_1_4: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4; break; @@ -3817,9 +3821,9 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, case HIERARCHY_NONE: default: operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M; - /* fall through , try first guess SC_RA_RAM_OP_PARAM_HIER_NO */ + /* try first guess SC_RA_RAM_OP_PARAM_HIER_NO */ /* transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */ - /* break; */ + /* fall through */ case HIERARCHY_1: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1; break; @@ -3837,7 +3841,8 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, case QAM_AUTO: default: operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M; - /* fall through , try first guess DRX_CONSTELLATION_QAM64 */ + /* try first guess DRX_CONSTELLATION_QAM64 */ + /* fall through */ case QAM_64: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; break; @@ -3880,7 +3885,8 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, case FEC_AUTO: default: operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M; - /* fall through , try first guess DRX_CODERATE_2DIV3 */ + /* try first guess DRX_CODERATE_2DIV3 */ + /* fall through */ case FEC_2_3: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3; break; @@ -3914,7 +3920,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, switch (state->props.bandwidth_hz) { case 0: state->props.bandwidth_hz = 8000000; - /* fall though */ + /* fall through */ case 8000000: bandwidth = DRXK_BANDWIDTH_8MHZ_IN_HZ; status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, diff --git a/drivers/media/dvb-frontends/mt352.c b/drivers/media/dvb-frontends/mt352.c index e127090f2d22..d5fa96f0a6cd 100644 --- a/drivers/media/dvb-frontends/mt352.c +++ b/drivers/media/dvb-frontends/mt352.c @@ -211,6 +211,7 @@ static int mt352_set_parameters(struct dvb_frontend *fe) if (op->hierarchy == HIERARCHY_AUTO || op->hierarchy == HIERARCHY_NONE) break; + /* fall through */ default: return -EINVAL; } diff --git a/drivers/media/dvb-frontends/or51132.c b/drivers/media/dvb-frontends/or51132.c index 62aa00767015..5f2549c48eb0 100644 --- a/drivers/media/dvb-frontends/or51132.c +++ b/drivers/media/dvb-frontends/or51132.c @@ -493,8 +493,8 @@ start: switch (reg&0xff) { case 0x06: if (reg & 0x1000) usK = 3 << 24; - /* Fall through to QAM64 case */ - case 0x43: + /* fall through */ + case 0x43: /* QAM64 */ c = 150204167; break; case 0x45: diff --git a/drivers/media/dvb-frontends/s5h1411.c b/drivers/media/dvb-frontends/s5h1411.c index f29750a96196..dd09336a135b 100644 --- a/drivers/media/dvb-frontends/s5h1411.c +++ b/drivers/media/dvb-frontends/s5h1411.c @@ -51,7 +51,7 @@ static int debug; #define dprintk(arg...) do { \ if (debug) \ printk(arg); \ - } while (0) +} while (0) /* Register values to initialise the demod, defaults to VSB */ static struct init_tab { @@ -410,7 +410,7 @@ static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz) default: dprintk("%s(%d KHz) Invalid, defaulting to 5380\n", __func__, KHz); - /* no break, need to continue */ + /* fall through */ case 5380: case 44000: s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1be4); diff --git a/drivers/media/dvb-frontends/zl10353.c b/drivers/media/dvb-frontends/zl10353.c index 47c0549eb7b2..1c689f7f4ab8 100644 --- a/drivers/media/dvb-frontends/zl10353.c +++ b/drivers/media/dvb-frontends/zl10353.c @@ -211,7 +211,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe) break; default: c->bandwidth_hz = 8000000; - /* fall though */ + /* fall through */ case 8000000: zl10353_single_write(fe, MCLK_RATIO, 0x75); zl10353_single_write(fe, 0x64, 0x36); @@ -268,6 +268,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe) if (c->hierarchy == HIERARCHY_AUTO || c->hierarchy == HIERARCHY_NONE) break; + /* fall through */ default: return -EINVAL; } diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index aaa9471c7d11..c380e2475c82 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -209,6 +209,7 @@ config VIDEO_ADV7604 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API depends on GPIOLIB || COMPILE_TEST select HDMI + select V4L2_FWNODE ---help--- Support for the Analog Devices ADV7604 video decoder. @@ -324,6 +325,7 @@ config VIDEO_TC358743 tristate "Toshiba TC358743 decoder" depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API select HDMI + select V4L2_FWNODE ---help--- Support for the Toshiba TC358743 HDMI to MIPI CSI-2 bridge. @@ -333,6 +335,7 @@ config VIDEO_TC358743 config VIDEO_TVP514X tristate "Texas Instruments TVP514x video decoder" depends on VIDEO_V4L2 && I2C + select V4L2_FWNODE ---help--- This is a Video4Linux2 sensor-level driver for the TI TVP5146/47 decoder. It is currently working with the TI OMAP3 camera @@ -344,6 +347,7 @@ config VIDEO_TVP514X config VIDEO_TVP5150 tristate "Texas Instruments TVP5150 video decoder" depends on VIDEO_V4L2 && I2C + select V4L2_FWNODE ---help--- Support for the Texas Instruments TVP5150 video decoder. @@ -353,6 +357,7 @@ config VIDEO_TVP5150 config VIDEO_TVP7002 tristate "Texas Instruments TVP7002 video decoder" depends on VIDEO_V4L2 && I2C + select V4L2_FWNODE ---help--- Support for the Texas Instruments TVP7002 video decoder. @@ -535,6 +540,7 @@ config VIDEO_OV2659 tristate "OmniVision OV2659 sensor support" depends on VIDEO_V4L2 && I2C depends on MEDIA_CAMERA_SUPPORT + select V4L2_FWNODE ---help--- This is a Video4Linux2 sensor-level driver for the OmniVision OV2659 camera. @@ -547,6 +553,7 @@ config VIDEO_OV5645 depends on OF depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT + select V4L2_FWNODE ---help--- This is a Video4Linux2 sensor-level driver for the OmniVision OV5645 camera. @@ -558,6 +565,7 @@ config VIDEO_OV5647 tristate "OmniVision OV5647 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT + select V4L2_FWNODE ---help--- This is a Video4Linux2 sensor-level driver for the OmniVision OV5647 camera. @@ -650,6 +658,7 @@ config VIDEO_MT9V032 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT select REGMAP_I2C + select V4L2_FWNODE ---help--- This is a Video4Linux2 sensor-level driver for the Micron MT9V032 752x480 CMOS sensor. @@ -697,6 +706,7 @@ config VIDEO_S5K4ECGX config VIDEO_S5K5BAF tristate "Samsung S5K5BAF sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + select V4L2_FWNODE ---help--- This is a V4L2 sensor-level driver for Samsung S5K5BAF 2M camera sensor with an embedded SoC image signal processor. @@ -707,6 +717,7 @@ source "drivers/media/i2c/et8ek8/Kconfig" config VIDEO_S5C73M3 tristate "Samsung S5C73M3 sensor support" depends on I2C && SPI && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + select V4L2_FWNODE ---help--- This is a V4L2 sensor-level driver for Samsung S5C73M3 8 Mpixel camera. diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index bdbbf8cf27e4..78de7ddf5081 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -1452,6 +1452,8 @@ static SIMPLE_DEV_PM_OPS(adv7180_pm_ops, adv7180_suspend, adv7180_resume); #ifdef CONFIG_OF static const struct of_device_id adv7180_of_id[] = { { .compatible = "adi,adv7180", }, + { .compatible = "adi,adv7180cp", }, + { .compatible = "adi,adv7180st", }, { .compatible = "adi,adv7182", }, { .compatible = "adi,adv7280", }, { .compatible = "adi,adv7280-m", }, diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index f1fa9cec489f..660bacb8f7d9 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -33,6 +33,7 @@ #include <linux/i2c.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of_graph.h> #include <linux/slab.h> #include <linux/v4l2-dv-timings.h> #include <linux/videodev2.h> @@ -45,7 +46,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-event.h> #include <media/v4l2-dv-timings.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> static int debug; module_param(debug, int, 0644); @@ -3069,7 +3070,7 @@ MODULE_DEVICE_TABLE(of, adv76xx_of_id); static int adv76xx_parse_dt(struct adv76xx_state *state) { - struct v4l2_of_endpoint bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg; struct device_node *endpoint; struct device_node *np; unsigned int flags; @@ -3083,7 +3084,7 @@ static int adv76xx_parse_dt(struct adv76xx_state *state) if (!endpoint) return -EINVAL; - ret = v4l2_of_parse_endpoint(endpoint, &bus_cfg); + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), &bus_cfg); if (ret) { of_node_put(endpoint); return ret; diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index b8d3c070bfc1..39f51daa7558 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c @@ -416,11 +416,13 @@ static void cx25840_initialize(struct i2c_client *client) INIT_WORK(&state->fw_work, cx25840_work_handler); init_waitqueue_head(&state->fw_wait); q = create_singlethread_workqueue("cx25840_fw"); - prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE); - queue_work(q, &state->fw_work); - schedule(); - finish_wait(&state->fw_wait, &wait); - destroy_workqueue(q); + if (q) { + prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE); + queue_work(q, &state->fw_work); + schedule(); + finish_wait(&state->fw_wait, &wait); + destroy_workqueue(q); + } /* 6. */ cx25840_write(client, 0x115, 0x8c); @@ -630,11 +632,13 @@ static void cx23885_initialize(struct i2c_client *client) INIT_WORK(&state->fw_work, cx25840_work_handler); init_waitqueue_head(&state->fw_wait); q = create_singlethread_workqueue("cx25840_fw"); - prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE); - queue_work(q, &state->fw_work); - schedule(); - finish_wait(&state->fw_wait, &wait); - destroy_workqueue(q); + if (q) { + prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE); + queue_work(q, &state->fw_work); + schedule(); + finish_wait(&state->fw_wait, &wait); + destroy_workqueue(q); + } /* Call the cx23888 specific std setup func, we no longer rely on * the generic cx24840 func. @@ -748,11 +752,13 @@ static void cx231xx_initialize(struct i2c_client *client) INIT_WORK(&state->fw_work, cx25840_work_handler); init_waitqueue_head(&state->fw_wait); q = create_singlethread_workqueue("cx25840_fw"); - prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE); - queue_work(q, &state->fw_work); - schedule(); - finish_wait(&state->fw_wait, &wait); - destroy_workqueue(q); + if (q) { + prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE); + queue_work(q, &state->fw_work); + schedule(); + finish_wait(&state->fw_wait, &wait); + destroy_workqueue(q); + } cx25840_std_setup(client); diff --git a/drivers/media/i2c/msp3400-kthreads.c b/drivers/media/i2c/msp3400-kthreads.c index 11fc593ed908..4dd01e9f553b 100644 --- a/drivers/media/i2c/msp3400-kthreads.c +++ b/drivers/media/i2c/msp3400-kthreads.c @@ -655,6 +655,7 @@ restart: break; case 0: /* 4.5 */ state->detected_std = V4L2_STD_MN; + /* fall-through */ default: no_second: state->second = msp3400c_carrier_detect_main[max1].cdo; diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 2e7a6e62a358..8a430640c85d 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -19,6 +19,7 @@ #include <linux/log2.h> #include <linux/mutex.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <linux/regmap.h> #include <linux/slab.h> #include <linux/videodev2.h> @@ -28,7 +29,7 @@ #include <media/i2c/mt9v032.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include <media/v4l2-subdev.h> /* The first four rows are black rows. The active area spans 753x481 pixels. */ @@ -979,7 +980,7 @@ static struct mt9v032_platform_data * mt9v032_get_pdata(struct i2c_client *client) { struct mt9v032_platform_data *pdata = NULL; - struct v4l2_of_endpoint endpoint; + struct v4l2_fwnode_endpoint endpoint; struct device_node *np; struct property *prop; @@ -990,7 +991,7 @@ mt9v032_get_pdata(struct i2c_client *client) if (!np) return NULL; - if (v4l2_of_parse_endpoint(np, &endpoint) < 0) + if (v4l2_fwnode_endpoint_parse(of_fwnode_handle(np), &endpoint) < 0) goto done; pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 6e6367214d40..122dd6c5eb38 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -42,9 +42,9 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-event.h> +#include <media/v4l2-fwnode.h> #include <media/v4l2-image-sizes.h> #include <media/v4l2-mediabus.h> -#include <media/v4l2-of.h> #include <media/v4l2-subdev.h> #define DRIVER_NAME "ov2659" @@ -1308,7 +1308,8 @@ static const struct v4l2_subdev_internal_ops ov2659_subdev_internal_ops = { static int ov2659_detect(struct v4l2_subdev *sd) { struct i2c_client *client = v4l2_get_subdevdata(sd); - u8 pid, ver; + u8 pid = 0; + u8 ver = 0; int ret; dev_dbg(&client->dev, "%s:\n", __func__); @@ -1346,7 +1347,7 @@ static struct ov2659_platform_data * ov2659_get_pdata(struct i2c_client *client) { struct ov2659_platform_data *pdata; - struct v4l2_of_endpoint *bus_cfg; + struct v4l2_fwnode_endpoint *bus_cfg; struct device_node *endpoint; if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) @@ -1356,7 +1357,7 @@ ov2659_get_pdata(struct i2c_client *client) if (!endpoint) return NULL; - bus_cfg = v4l2_of_alloc_parse_endpoint(endpoint); + bus_cfg = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(endpoint)); if (IS_ERR(bus_cfg)) { pdata = NULL; goto done; @@ -1376,7 +1377,7 @@ ov2659_get_pdata(struct i2c_client *client) pdata->link_frequency = bus_cfg->link_frequencies[0]; done: - v4l2_of_free_endpoint(bus_cfg); + v4l2_fwnode_endpoint_free(bus_cfg); of_node_put(endpoint); return pdata; } diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c index 57bd591ea54b..d1e844f7f03f 100644 --- a/drivers/media/i2c/ov5645.c +++ b/drivers/media/i2c/ov5645.c @@ -39,7 +39,7 @@ #include <linux/slab.h> #include <linux/types.h> #include <media/v4l2-ctrls.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include <media/v4l2-subdev.h> #define OV5645_VOLTAGE_ANALOG 2800000 @@ -87,7 +87,7 @@ struct ov5645 { struct device *dev; struct v4l2_subdev sd; struct media_pad pad; - struct v4l2_of_endpoint ep; + struct v4l2_fwnode_endpoint ep; struct v4l2_mbus_framefmt fmt; struct v4l2_rect crop; struct clk *xclk; @@ -1102,7 +1102,8 @@ static int ov5645_probe(struct i2c_client *client, return -EINVAL; } - ret = v4l2_of_parse_endpoint(endpoint, &ov5645->ep); + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), + &ov5645->ep); if (ret < 0) { dev_err(dev, "parsing endpoint node failed\n"); return ret; diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index f57a0b354cf6..95ce90fdb876 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -25,12 +25,13 @@ #include <linux/init.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/of_graph.h> #include <linux/slab.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> +#include <media/v4l2-fwnode.h> #include <media/v4l2-image-sizes.h> #include <media/v4l2-mediabus.h> -#include <media/v4l2-of.h> #define SENSOR_NAME "ov5647" @@ -510,7 +511,7 @@ static const struct v4l2_subdev_internal_ops ov5647_subdev_internal_ops = { static int ov5647_parse_dt(struct device_node *np) { - struct v4l2_of_endpoint bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg; struct device_node *ep; int ret; @@ -519,7 +520,7 @@ static int ov5647_parse_dt(struct device_node *np) if (!ep) return -EINVAL; - ret = v4l2_of_parse_endpoint(ep, &bus_cfg); + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg); of_node_put(ep); return ret; diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 3844853ab0a0..f434fb2ee6fc 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -24,6 +24,7 @@ #include <linux/media.h> #include <linux/module.h> #include <linux/of_gpio.h> +#include <linux/of_graph.h> #include <linux/regulator/consumer.h> #include <linux/sizes.h> #include <linux/slab.h> @@ -35,7 +36,7 @@ #include <media/v4l2-subdev.h> #include <media/v4l2-mediabus.h> #include <media/i2c/s5c73m3.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include "s5c73m3.h" @@ -1602,7 +1603,7 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state) const struct s5c73m3_platform_data *pdata = dev->platform_data; struct device_node *node = dev->of_node; struct device_node *node_ep; - struct v4l2_of_endpoint ep; + struct v4l2_fwnode_endpoint ep; int ret; if (!node) { @@ -1639,7 +1640,7 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state) return 0; } - ret = v4l2_of_parse_endpoint(node_ep, &ep); + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(node_ep), &ep); of_node_put(node_ep); if (ret) return ret; diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index db82ed05792e..962051b9939d 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -30,7 +30,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-subdev.h> #include <media/v4l2-mediabus.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> static int debug; module_param(debug, int, 0644); @@ -1841,7 +1841,7 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev) { struct device_node *node = dev->of_node; struct device_node *node_ep; - struct v4l2_of_endpoint ep; + struct v4l2_fwnode_endpoint ep; int ret; if (!node) { @@ -1868,7 +1868,7 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev) return -EINVAL; } - ret = v4l2_of_parse_endpoint(node_ep, &ep); + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(node_ep), &ep); of_node_put(node_ep); if (ret) return ret; diff --git a/drivers/media/i2c/smiapp/Kconfig b/drivers/media/i2c/smiapp/Kconfig index 3149cda1d0db..f59718d8e51e 100644 --- a/drivers/media/i2c/smiapp/Kconfig +++ b/drivers/media/i2c/smiapp/Kconfig @@ -3,5 +3,6 @@ config VIDEO_SMIAPP depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAVE_CLK depends on MEDIA_CAMERA_SUPPORT select VIDEO_SMIAPP_PLL + select V4L2_FWNODE ---help--- This is a generic driver for SMIA++/SMIA camera modules. diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index f4e92bdfe192..e0b0c032c4ac 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -27,12 +27,13 @@ #include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/pm_runtime.h> +#include <linux/property.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> #include <linux/smiapp.h> #include <linux/v4l2-mediabus.h> +#include <media/v4l2-fwnode.h> #include <media/v4l2-device.h> -#include <media/v4l2-of.h> #include "smiapp.h" @@ -2784,19 +2785,20 @@ static int __maybe_unused smiapp_resume(struct device *dev) static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev) { struct smiapp_hwconfig *hwcfg; - struct v4l2_of_endpoint *bus_cfg; - struct device_node *ep; + struct v4l2_fwnode_endpoint *bus_cfg; + struct fwnode_handle *ep; + struct fwnode_handle *fwnode = dev_fwnode(dev); int i; int rval; - if (!dev->of_node) + if (!fwnode) return dev->platform_data; - ep = of_graph_get_next_endpoint(dev->of_node, NULL); + ep = fwnode_graph_get_next_endpoint(fwnode, NULL); if (!ep) return NULL; - bus_cfg = v4l2_of_alloc_parse_endpoint(ep); + bus_cfg = v4l2_fwnode_endpoint_alloc_parse(ep); if (IS_ERR(bus_cfg)) goto out_err; @@ -2817,11 +2819,10 @@ static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev) dev_dbg(dev, "lanes %u\n", hwcfg->lanes); /* NVM size is not mandatory */ - of_property_read_u32(dev->of_node, "nokia,nvm-size", - &hwcfg->nvm_size); + fwnode_property_read_u32(fwnode, "nokia,nvm-size", &hwcfg->nvm_size); - rval = of_property_read_u32(dev->of_node, "clock-frequency", - &hwcfg->ext_clk); + rval = fwnode_property_read_u32(fwnode, "clock-frequency", + &hwcfg->ext_clk); if (rval) { dev_warn(dev, "can't get clock-frequency\n"); goto out_err; @@ -2846,13 +2847,13 @@ static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev) dev_dbg(dev, "freq %d: %lld\n", i, hwcfg->op_sys_clock[i]); } - v4l2_of_free_endpoint(bus_cfg); - of_node_put(ep); + v4l2_fwnode_endpoint_free(bus_cfg); + fwnode_handle_put(ep); return hwcfg; out_err: - v4l2_of_free_endpoint(bus_cfg); - of_node_put(ep); + v4l2_fwnode_endpoint_free(bus_cfg); + fwnode_handle_put(ep); return NULL; } diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c index dbd6d92c589f..d2be64d54b22 100644 --- a/drivers/media/i2c/soc_camera/ov6650.c +++ b/drivers/media/i2c/soc_camera/ov6650.c @@ -709,6 +709,7 @@ static int ov6650_set_fmt(struct v4l2_subdev *sd, switch (mf->code) { case MEDIA_BUS_FMT_Y10_1X10: mf->code = MEDIA_BUS_FMT_Y8_1X8; + /* fall through */ case MEDIA_BUS_FMT_Y8_1X8: case MEDIA_BUS_FMT_YVYU8_2X8: case MEDIA_BUS_FMT_YUYV8_2X8: @@ -718,6 +719,7 @@ static int ov6650_set_fmt(struct v4l2_subdev *sd, break; default: mf->code = MEDIA_BUS_FMT_SBGGR8_1X8; + /* fall through */ case MEDIA_BUS_FMT_SBGGR8_1X8: mf->colorspace = V4L2_COLORSPACE_SRGB; break; diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index acef4eca269f..3e5b09030303 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -33,6 +33,7 @@ #include <linux/delay.h> #include <linux/gpio/consumer.h> #include <linux/interrupt.h> +#include <linux/of_graph.h> #include <linux/videodev2.h> #include <linux/workqueue.h> #include <linux/v4l2-dv-timings.h> @@ -41,7 +42,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-event.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include <media/i2c/tc358743.h> #include "tc358743_regs.h" @@ -76,7 +77,7 @@ static const struct v4l2_dv_timings_cap tc358743_timings_cap = { struct tc358743_state { struct tc358743_platform_data pdata; - struct v4l2_of_bus_mipi_csi2 bus; + struct v4l2_fwnode_bus_mipi_csi2 bus; struct v4l2_subdev sd; struct media_pad pad; struct v4l2_ctrl_handler hdl; @@ -223,7 +224,7 @@ static void i2c_wr8(struct v4l2_subdev *sd, u16 reg, u8 val) static void i2c_wr8_and_or(struct v4l2_subdev *sd, u16 reg, u8 mask, u8 val) { - i2c_wrreg(sd, reg, (i2c_rdreg(sd, reg, 2) & mask) | val, 2); + i2c_wrreg(sd, reg, (i2c_rdreg(sd, reg, 1) & mask) | val, 1); } static u16 i2c_rd16(struct v4l2_subdev *sd, u16 reg) @@ -1695,7 +1696,7 @@ static void tc358743_gpio_reset(struct tc358743_state *state) static int tc358743_probe_of(struct tc358743_state *state) { struct device *dev = &state->i2c_client->dev; - struct v4l2_of_endpoint *endpoint; + struct v4l2_fwnode_endpoint *endpoint; struct device_node *ep; struct clk *refclk; u32 bps_pr_lane; @@ -1715,7 +1716,7 @@ static int tc358743_probe_of(struct tc358743_state *state) return -EINVAL; } - endpoint = v4l2_of_alloc_parse_endpoint(ep); + endpoint = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep)); if (IS_ERR(endpoint)) { dev_err(dev, "failed to parse endpoint\n"); return PTR_ERR(endpoint); @@ -1803,7 +1804,7 @@ static int tc358743_probe_of(struct tc358743_state *state) disable_clk: clk_disable_unprepare(refclk); free_endpoint: - v4l2_of_free_endpoint(endpoint); + v4l2_fwnode_endpoint_free(endpoint); return ret; } #else diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 07853d2252aa..ad2df998f9c5 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -38,7 +38,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-common.h> #include <media/v4l2-mediabus.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include <media/v4l2-ctrls.h> #include <media/i2c/tvp514x.h> #include <media/media-entity.h> @@ -998,7 +998,7 @@ static struct tvp514x_platform_data * tvp514x_get_pdata(struct i2c_client *client) { struct tvp514x_platform_data *pdata = NULL; - struct v4l2_of_endpoint bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg; struct device_node *endpoint; unsigned int flags; @@ -1009,7 +1009,7 @@ tvp514x_get_pdata(struct i2c_client *client) if (!endpoint) return NULL; - if (v4l2_of_parse_endpoint(endpoint, &bus_cfg)) + if (v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), &bus_cfg)) goto done; pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 04e96b3057bb..9da4bf4f2c7a 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -12,10 +12,11 @@ #include <linux/delay.h> #include <linux/gpio/consumer.h> #include <linux/module.h> +#include <linux/of_graph.h> #include <media/v4l2-async.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include <media/v4l2-mc.h> #include "tvp5150_reg.h" @@ -1358,7 +1359,7 @@ static int tvp5150_init(struct i2c_client *c) static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) { - struct v4l2_of_endpoint bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg; struct device_node *ep; #ifdef CONFIG_MEDIA_CONTROLLER struct device_node *connectors, *child; @@ -1373,7 +1374,7 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) if (!ep) return -EINVAL; - ret = v4l2_of_parse_endpoint(ep, &bus_cfg); + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg); if (ret) goto err; diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 4c1190127c85..a26c1a3f7183 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -33,7 +33,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include "tvp7002_reg.h" @@ -889,7 +889,7 @@ static const struct v4l2_subdev_ops tvp7002_ops = { static struct tvp7002_config * tvp7002_get_pdata(struct i2c_client *client) { - struct v4l2_of_endpoint bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg; struct tvp7002_config *pdata = NULL; struct device_node *endpoint; unsigned int flags; @@ -901,7 +901,7 @@ tvp7002_get_pdata(struct i2c_client *client) if (!endpoint) return NULL; - if (v4l2_of_parse_endpoint(endpoint, &bus_cfg)) + if (v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), &bus_cfg)) goto done; pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); diff --git a/drivers/media/pci/bt8xx/dst_ca.c b/drivers/media/pci/bt8xx/dst_ca.c index 04d06c564602..90f4263452d3 100644 --- a/drivers/media/pci/bt8xx/dst_ca.c +++ b/drivers/media/pci/bt8xx/dst_ca.c @@ -637,6 +637,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !"); + break; default: result = -EOPNOTSUPP; } diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c index d5c911c09e2b..f8e173f3e9e2 100644 --- a/drivers/media/pci/cobalt/cobalt-driver.c +++ b/drivers/media/pci/cobalt/cobalt-driver.c @@ -205,6 +205,8 @@ void cobalt_pcie_status_show(struct cobalt *cobalt) offset = pci_find_capability(pci_dev, PCI_CAP_ID_EXP); bus_offset = pci_find_capability(pci_bus_dev, PCI_CAP_ID_EXP); + if (!offset || !bus_offset) + return; /* Device */ pci_read_config_dword(pci_dev, offset + PCI_EXP_DEVCAP, &capa); diff --git a/drivers/media/pci/cx18/cx18-dvb.c b/drivers/media/pci/cx18/cx18-dvb.c index d130d65828b0..53f4d6bf81fb 100644 --- a/drivers/media/pci/cx18/cx18-dvb.c +++ b/drivers/media/pci/cx18/cx18-dvb.c @@ -151,7 +151,7 @@ static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream, } if (ret) { - CX18_ERR("The MPC718 board variant with the MT352 DVB-Tdemodualtor will not work without it\n"); + CX18_ERR("The MPC718 board variant with the MT352 DVB-T demodulator will not work without it\n"); CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware mpc718' if you need the firmware\n"); } return ret; diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c index 9e39aea85df6..c48fa8e25a70 100644 --- a/drivers/media/pci/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c @@ -2081,7 +2081,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; - /* break omitted intentionally */ + /* fall-through */ case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP: ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ @@ -2238,6 +2238,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) /* Currently only enabled for the integrated IR controller */ if (!enable_885_ir) break; + /* fall-through */ case CX23885_BOARD_HAUPPAUGE_HVR1250: case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE: diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c index 73cc7a67a8bc..6df21b29ea17 100644 --- a/drivers/media/pci/cx88/cx88-cards.c +++ b/drivers/media/pci/cx88/cx88-cards.c @@ -3681,7 +3681,14 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) core->nr = nr; sprintf(core->name, "cx88[%d]", core->nr); - core->tvnorm = V4L2_STD_NTSC_M; + /* + * Note: Setting initial standard here would cause first call to + * cx88_set_tvnorm() to return without programming any registers. Leave + * it blank for at this point and it will get set later in + * cx8800_initdev() + */ + core->tvnorm = 0; + core->width = 320; core->height = 240; core->field = V4L2_FIELD_INTERLACED; diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index c7d4e87ccb64..7d25ecd4404b 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c @@ -1420,7 +1420,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev, request_module("rtc-isl1208"); core->i2c_rtc = i2c_new_device(&core->i2c_adap, &rtc_info); } - /* break intentionally omitted */ + /* fall-through */ case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: request_module("ir-kbd-i2c"); } @@ -1435,7 +1435,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev, /* initial device configuration */ mutex_lock(&core->lock); - cx88_set_tvnorm(core, core->tvnorm); + cx88_set_tvnorm(core, V4L2_STD_NTSC_M); v4l2_ctrl_handler_setup(&core->video_hdl); v4l2_ctrl_handler_setup(&core->audio_hdl); cx88_video_mux(core, 0); diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c index 340cff02dee2..09b5338f4f8b 100644 --- a/drivers/media/pci/ddbridge/ddbridge-core.c +++ b/drivers/media/pci/ddbridge/ddbridge-core.c @@ -789,9 +789,10 @@ static void dvb_input_detach(struct ddb_input *input) dvb_frontend_detach(input->fe); input->fe = NULL; } + /* fall-through */ case 4: dvb_net_release(&input->dvbnet); - + /* fall-through */ case 3: dvbdemux->dmx.close(&dvbdemux->dmx); dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, @@ -799,10 +800,10 @@ static void dvb_input_detach(struct ddb_input *input) dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &input->mem_frontend); dvb_dmxdev_release(&input->dmxdev); - + /* fall-through */ case 2: dvb_dmx_release(&input->demux); - + /* fall-through */ case 1: dvb_unregister_adapter(adap); } diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c index f79380faf499..9965d3531c80 100644 --- a/drivers/media/pci/saa7134/saa7134-cards.c +++ b/drivers/media/pci/saa7134/saa7134-cards.c @@ -7806,7 +7806,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->name, saa7134_boards[dev->board].name); break; } - /* break intentionally omitted */ + /* fall-through */ case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: case SAA7134_BOARD_ASUS_EUROPA_HYBRID: @@ -7864,7 +7864,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) break; case SAA7134_BOARD_HAUPPAUGE_HVR1110: hauppauge_eeprom(dev, dev->eedata+0x80); - /* break intentionally omitted */ + /* fall-through */ case SAA7134_BOARD_PINNACLE_PCTV_310i: case SAA7134_BOARD_KWORLD_DVBT_210: case SAA7134_BOARD_TEVION_DVBT_220RF: diff --git a/drivers/media/pci/saa7164/saa7164-bus.c b/drivers/media/pci/saa7164/saa7164-bus.c index b2ff82fa7116..ecfeac5cdbed 100644 --- a/drivers/media/pci/saa7164/saa7164-bus.c +++ b/drivers/media/pci/saa7164/saa7164-bus.c @@ -389,11 +389,11 @@ int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, msg_tmp.size = le16_to_cpu((__force __le16)msg_tmp.size); msg_tmp.command = le32_to_cpu((__force __le32)msg_tmp.command); msg_tmp.controlselector = le16_to_cpu((__force __le16)msg_tmp.controlselector); + memcpy(msg, &msg_tmp, sizeof(*msg)); /* No need to update the read positions, because this was a peek */ /* If the caller specifically want to peek, return */ if (peekonly) { - memcpy(msg, &msg_tmp, sizeof(*msg)); goto peekout; } @@ -438,21 +438,15 @@ int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, space_rem = bus->m_dwSizeGetRing - curr_grp; if (space_rem < sizeof(*msg)) { - /* msg wraps around the ring */ - memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, space_rem); - memcpy_fromio((u8 *)msg + space_rem, bus->m_pdwGetRing, - sizeof(*msg) - space_rem); if (buf) memcpy_fromio(buf, bus->m_pdwGetRing + sizeof(*msg) - space_rem, buf_size); } else if (space_rem == sizeof(*msg)) { - memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); if (buf) memcpy_fromio(buf, bus->m_pdwGetRing, buf_size); } else { /* Additional data wraps around the ring */ - memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); if (buf) { memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg), space_rem - sizeof(*msg)); @@ -465,15 +459,10 @@ int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, } else { /* No wrapping */ - memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); if (buf) memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg), buf_size); } - /* Convert from little endian to CPU */ - msg->size = le16_to_cpu((__force __le16)msg->size); - msg->command = le32_to_cpu((__force __le32)msg->command); - msg->controlselector = le16_to_cpu((__force __le16)msg->controlselector); /* Update the read positions, adjusting the ring */ saa7164_writel(bus->m_dwGetReadPos, new_grp); diff --git a/drivers/media/pci/saa7164/saa7164-cmd.c b/drivers/media/pci/saa7164/saa7164-cmd.c index 175015ca79f2..dfebd77ada59 100644 --- a/drivers/media/pci/saa7164/saa7164-cmd.c +++ b/drivers/media/pci/saa7164/saa7164-cmd.c @@ -506,6 +506,8 @@ int saa7164_cmd_send(struct saa7164_dev *dev, u8 id, enum tmComResCmd command, dprintk(DBGLVL_CMD, "%s() UNKNOWN OR INVALID CONTROL\n", __func__); + ret = SAA_ERR_NOT_SUPPORTED; + break; default: dprintk(DBGLVL_CMD, "%s() UNKNOWN\n", __func__); ret = SAA_ERR_NOT_SUPPORTED; diff --git a/drivers/media/pci/solo6x10/solo6x10-core.c b/drivers/media/pci/solo6x10/solo6x10-core.c index f50d07229236..ca0873e47bea 100644 --- a/drivers/media/pci/solo6x10/solo6x10-core.c +++ b/drivers/media/pci/solo6x10/solo6x10-core.c @@ -511,6 +511,7 @@ static int solo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) default: dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, assuming 4 ch\n", chip_id); + /* fall through */ case 5: solo_dev->nr_chans = 4; solo_dev->nr_ext = 1; diff --git a/drivers/media/pci/solo6x10/solo6x10-i2c.c b/drivers/media/pci/solo6x10/solo6x10-i2c.c index e83bb79f9349..89f2f2a493c2 100644 --- a/drivers/media/pci/solo6x10/solo6x10-i2c.c +++ b/drivers/media/pci/solo6x10/solo6x10-i2c.c @@ -192,6 +192,7 @@ int solo_i2c_isr(struct solo_dev *solo_dev) } solo_dev->i2c_state = IIC_STATE_WRITE; + /* fall through */ case IIC_STATE_WRITE: ret = solo_i2c_handle_write(solo_dev); break; diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c index df9395c87178..f2905bd80366 100644 --- a/drivers/media/pci/ttpci/av7110.c +++ b/drivers/media/pci/ttpci/av7110.c @@ -336,6 +336,7 @@ static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len, av7110_p2t_write(buffer1, buffer1_len, dvbdmxfilter->feed->pid, &av7110->p2t_filter[dvbdmxfilter->index]); + return 0; default: return 0; } @@ -451,8 +452,12 @@ static void debiirq(unsigned long cookie) case DATA_CI_PUT: dprintk(4, "debi DATA_CI_PUT\n"); + xfer = TX_BUFF; + break; case DATA_MPEG_PLAY: dprintk(4, "debi DATA_MPEG_PLAY\n"); + xfer = TX_BUFF; + break; case DATA_BMP_LOAD: dprintk(4, "debi DATA_BMP_LOAD\n"); xfer = TX_BUFF; diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c index 180f3d7af3e1..a11cb501c550 100644 --- a/drivers/media/pci/zoran/zoran_driver.c +++ b/drivers/media/pci/zoran/zoran_driver.c @@ -534,6 +534,7 @@ static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num) KERN_WARNING "%s: %s - queueing buffer %d in state DONE!?\n", ZR_DEVNAME(zr), __func__, num); + /* fall through */ case BUZ_STATE_USER: /* since there is at least one unused buffer there's room for at least * one more pend[] entry */ @@ -693,6 +694,7 @@ static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, KERN_WARNING "%s: %s - queing frame in BUZ_STATE_DONE state!?\n", ZR_DEVNAME(zr), __func__); + /* fall through */ case BUZ_STATE_USER: /* since there is at least one unused buffer there's room for at *least one more pend[] entry */ diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 041cb80a26b1..288d3b0dc812 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -82,6 +82,7 @@ config VIDEO_OMAP3 select ARM_DMA_USE_IOMMU select VIDEOBUF2_DMA_CONTIG select MFD_SYSCON + select V4L2_FWNODE ---help--- Driver for an OMAP 3 camera controller. @@ -97,6 +98,7 @@ config VIDEO_PXA27x depends on PXA27x || COMPILE_TEST select VIDEOBUF2_DMA_SG select SG_SPLIT + select V4L2_FWNODE ---help--- This is a v4l2 driver for the PXA27x Quick Capture Interface @@ -114,6 +116,19 @@ config VIDEO_S3C_CAMIF To compile this driver as a module, choose M here: the module will be called s3c-camif. +config VIDEO_STM32_DCMI + tristate "STM32 Digital Camera Memory Interface (DCMI) support" + depends on VIDEO_V4L2 && OF && HAS_DMA + depends on ARCH_STM32 || COMPILE_TEST + select VIDEOBUF2_DMA_CONTIG + select V4L2_FWNODE + ---help--- + This module makes the STM32 Digital Camera Memory Interface (DCMI) + available as a v4l2 device. + + To compile this driver as a module, choose M here: the module + will be called stm32-dcmi. + source "drivers/media/platform/soc_camera/Kconfig" source "drivers/media/platform/exynos4-is/Kconfig" source "drivers/media/platform/am437x/Kconfig" @@ -127,6 +142,7 @@ config VIDEO_TI_CAL depends on SOC_DRA7XX || COMPILE_TEST depends on HAS_DMA select VIDEOBUF2_DMA_CONTIG + select V4L2_FWNODE default n ---help--- Support for the TI CAL (Camera Adaptation Layer) block diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index 63303d63c64c..231f3c2894c9 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -68,6 +68,8 @@ obj-$(CONFIG_VIDEO_RCAR_VIN) += rcar-vin/ obj-$(CONFIG_VIDEO_ATMEL_ISC) += atmel/ obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel/ +obj-$(CONFIG_VIDEO_STM32_DCMI) += stm32/ + ccflags-y += -I$(srctree)/drivers/media/i2c obj-$(CONFIG_VIDEO_MEDIATEK_VPU) += mtk-vpu/ diff --git a/drivers/media/platform/am437x/Kconfig b/drivers/media/platform/am437x/Kconfig index 42d9c186710a..160e77e9a0fb 100644 --- a/drivers/media/platform/am437x/Kconfig +++ b/drivers/media/platform/am437x/Kconfig @@ -3,6 +3,7 @@ config VIDEO_AM437X_VPFE depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA depends on SOC_AM43XX || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG + select V4L2_FWNODE help Support for AM437x Video Processing Front End based Video Capture Driver. diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index 05489a401c5c..466aba8b0e00 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -26,6 +26,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/of_graph.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -36,7 +37,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-event.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include "am437x-vpfe.h" @@ -2303,7 +2304,8 @@ vpfe_async_bound(struct v4l2_async_notifier *notifier, vpfe_dbg(1, vpfe, "vpfe_async_bound\n"); for (i = 0; i < ARRAY_SIZE(vpfe->cfg->asd); i++) { - if (vpfe->cfg->asd[i]->match.of.node == asd[i].match.of.node) { + if (vpfe->cfg->asd[i]->match.fwnode.fwnode == + asd[i].match.fwnode.fwnode) { sdinfo = &vpfe->cfg->sub_devs[i]; vpfe->sd[i] = subdev; vpfe->sd[i]->grp_id = sdinfo->grp_id; @@ -2419,7 +2421,7 @@ static struct vpfe_config * vpfe_get_pdata(struct platform_device *pdev) { struct device_node *endpoint = NULL; - struct v4l2_of_endpoint bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg; struct vpfe_subdev_info *sdinfo; struct vpfe_config *pdata; unsigned int flags; @@ -2463,7 +2465,8 @@ vpfe_get_pdata(struct platform_device *pdev) sdinfo->vpfe_param.if_type = VPFE_RAW_BAYER; } - err = v4l2_of_parse_endpoint(endpoint, &bus_cfg); + err = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), + &bus_cfg); if (err) { dev_err(&pdev->dev, "Could not parse the endpoint\n"); goto done; @@ -2501,8 +2504,8 @@ vpfe_get_pdata(struct platform_device *pdev) goto done; } - pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_OF; - pdata->asd[i]->match.of.node = rem; + pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_FWNODE; + pdata->asd[i]->match.fwnode.fwnode = of_fwnode_handle(rem); of_node_put(rem); } diff --git a/drivers/media/platform/atmel/Kconfig b/drivers/media/platform/atmel/Kconfig index 9bd0f19b127f..55de751e5f51 100644 --- a/drivers/media/platform/atmel/Kconfig +++ b/drivers/media/platform/atmel/Kconfig @@ -4,6 +4,7 @@ config VIDEO_ATMEL_ISC depends on ARCH_AT91 || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select REGMAP_MMIO + select V4L2_FWNODE help This module makes the ATMEL Image Sensor Controller available as a v4l2 device. @@ -13,6 +14,7 @@ config VIDEO_ATMEL_ISI depends on VIDEO_V4L2 && OF && HAS_DMA depends on ARCH_AT91 || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG + select V4L2_FWNODE ---help--- This module makes the ATMEL Image Sensor Interface available as a v4l2 device. diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index c4b2115559a5..d6534252cdcd 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -32,6 +32,7 @@ #include <linux/math64.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> @@ -42,7 +43,7 @@ #include <media/v4l2-event.h> #include <media/v4l2-image-sizes.h> #include <media/v4l2-ioctl.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include <media/v4l2-subdev.h> #include <media/videobuf2-dma-contig.h> @@ -239,13 +240,11 @@ static struct isc_format isc_formats[] = { { V4L2_PIX_FMT_YUV420, 0x0, 12, ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_YYCC, - ISC_DCFG_IMODE_YC420P | ISC_DCFG_YMBSIZE_BEATS8 | - ISC_DCFG_CMBSIZE_BEATS8, ISC_DCTRL_DVIEW_PLANAR, 0x7fb, + ISC_DCFG_IMODE_YC420P, ISC_DCTRL_DVIEW_PLANAR, 0x7fb, false, false }, { V4L2_PIX_FMT_YUV422P, 0x0, 16, ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_YYCC, - ISC_DCFG_IMODE_YC422P | ISC_DCFG_YMBSIZE_BEATS8 | - ISC_DCFG_CMBSIZE_BEATS8, ISC_DCTRL_DVIEW_PLANAR, 0x3fb, + ISC_DCFG_IMODE_YC422P, ISC_DCTRL_DVIEW_PLANAR, 0x3fb, false, false }, { V4L2_PIX_FMT_RGB565, MEDIA_BUS_FMT_RGB565_2X8_LE, 16, ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_RGB565, @@ -700,8 +699,10 @@ static void isc_set_histogram(struct isc_device *isc) } static inline void isc_get_param(const struct isc_format *fmt, - u32 *rlp_mode, u32 *dcfg_imode) + u32 *rlp_mode, u32 *dcfg) { + *dcfg = ISC_DCFG_YMBSIZE_BEATS8; + switch (fmt->fourcc) { case V4L2_PIX_FMT_SBGGR10: case V4L2_PIX_FMT_SGBRG10: @@ -712,11 +713,11 @@ static inline void isc_get_param(const struct isc_format *fmt, case V4L2_PIX_FMT_SGRBG12: case V4L2_PIX_FMT_SRGGB12: *rlp_mode = fmt->reg_rlp_mode; - *dcfg_imode = fmt->reg_dcfg_imode; + *dcfg |= fmt->reg_dcfg_imode; break; default: *rlp_mode = ISC_RLP_CFG_MODE_DAT8; - *dcfg_imode = ISC_DCFG_IMODE_PACKED8; + *dcfg |= ISC_DCFG_IMODE_PACKED8; break; } } @@ -726,18 +727,19 @@ static int isc_configure(struct isc_device *isc) struct regmap *regmap = isc->regmap; const struct isc_format *current_fmt = isc->current_fmt; struct isc_subdev_entity *subdev = isc->current_subdev; - u32 pfe_cfg0, rlp_mode, dcfg_imode, mask, pipeline; + u32 pfe_cfg0, rlp_mode, dcfg, mask, pipeline; if (sensor_is_preferred(current_fmt)) { pfe_cfg0 = current_fmt->reg_bps; pipeline = 0x0; - isc_get_param(current_fmt, &rlp_mode, &dcfg_imode); + isc_get_param(current_fmt, &rlp_mode, &dcfg); isc->ctrls.hist_stat = HIST_INIT; } else { pfe_cfg0 = isc->raw_fmt->reg_bps; pipeline = current_fmt->pipeline; rlp_mode = current_fmt->reg_rlp_mode; - dcfg_imode = current_fmt->reg_dcfg_imode; + dcfg = current_fmt->reg_dcfg_imode | ISC_DCFG_YMBSIZE_BEATS8 | + ISC_DCFG_CMBSIZE_BEATS8; } pfe_cfg0 |= subdev->pfe_cfg0 | ISC_PFE_CFG0_MODE_PROGRESSIVE; @@ -750,7 +752,7 @@ static int isc_configure(struct isc_device *isc) regmap_update_bits(regmap, ISC_RLP_CFG, ISC_RLP_CFG_MODE_MASK, rlp_mode); - regmap_update_bits(regmap, ISC_DCFG, ISC_DCFG_IMODE_MASK, dcfg_imode); + regmap_write(regmap, ISC_DCFG, dcfg); /* Set the pipeline */ isc_set_pipeline(isc, pipeline); @@ -1684,7 +1686,7 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc) { struct device_node *np = dev->of_node; struct device_node *epn = NULL, *rem; - struct v4l2_of_endpoint v4l2_epn; + struct v4l2_fwnode_endpoint v4l2_epn; struct isc_subdev_entity *subdev_entity; unsigned int flags; int ret; @@ -1703,7 +1705,8 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc) continue; } - ret = v4l2_of_parse_endpoint(epn, &v4l2_epn); + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(epn), + &v4l2_epn); if (ret) { of_node_put(rem); ret = -EINVAL; @@ -1738,8 +1741,9 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc) if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_LOW; - subdev_entity->asd->match_type = V4L2_ASYNC_MATCH_OF; - subdev_entity->asd->match.of.node = rem; + subdev_entity->asd->match_type = V4L2_ASYNC_MATCH_FWNODE; + subdev_entity->asd->match.fwnode.fwnode = + of_fwnode_handle(rem); list_add_tail(&subdev_entity->list, &isc->subdev_entities); } diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c index e4867f84514c..ef482cc704fe 100644 --- a/drivers/media/platform/atmel/atmel-isi.c +++ b/drivers/media/platform/atmel/atmel-isi.c @@ -19,6 +19,7 @@ #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of_graph.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/slab.h> @@ -30,7 +31,7 @@ #include <media/v4l2-dev.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include <media/videobuf2-dma-contig.h> #include <media/v4l2-image-sizes.h> @@ -801,7 +802,7 @@ static int atmel_isi_parse_dt(struct atmel_isi *isi, struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct v4l2_of_endpoint ep; + struct v4l2_fwnode_endpoint ep; int err; /* Default settings for ISI */ @@ -814,7 +815,7 @@ static int atmel_isi_parse_dt(struct atmel_isi *isi, return -EINVAL; } - err = v4l2_of_parse_endpoint(np, &ep); + err = v4l2_fwnode_endpoint_parse(of_fwnode_handle(np), &ep); of_node_put(np); if (err) { dev_err(&pdev->dev, "Could not parse the endpoint\n"); @@ -1126,8 +1127,8 @@ static int isi_graph_parse(struct atmel_isi *isi, struct device_node *node) /* Remote node to connect */ isi->entity.node = remote; - isi->entity.asd.match_type = V4L2_ASYNC_MATCH_OF; - isi->entity.asd.match.of.node = remote; + isi->entity.asd.match_type = V4L2_ASYNC_MATCH_FWNODE; + isi->entity.asd.match.fwnode.fwnode = of_fwnode_handle(remote); return 0; } } diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index d523e990d509..4724dfef0643 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -430,10 +430,10 @@ static int coda_g_fmt(struct file *file, void *priv, f->fmt.pix.bytesperline = q_data->bytesperline; f->fmt.pix.sizeimage = q_data->sizeimage; - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG) - f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; - else - f->fmt.pix.colorspace = ctx->colorspace; + f->fmt.pix.colorspace = ctx->colorspace; + f->fmt.pix.xfer_func = ctx->xfer_func; + f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; + f->fmt.pix.quantization = ctx->quantization; return 0; } @@ -599,6 +599,9 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv, } f->fmt.pix.colorspace = ctx->colorspace; + f->fmt.pix.xfer_func = ctx->xfer_func; + f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; + f->fmt.pix.quantization = ctx->quantization; q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); codec = coda_find_codec(ctx->dev, q_data_src->fourcc, @@ -612,7 +615,6 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv, /* The h.264 decoder only returns complete 16x16 macroblocks */ if (codec && codec->src_fourcc == V4L2_PIX_FMT_H264) { - f->fmt.pix.width = f->fmt.pix.width; f->fmt.pix.height = round_up(f->fmt.pix.height, 16); f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16); f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * @@ -635,6 +637,23 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv, return 0; } +static void coda_set_default_colorspace(struct v4l2_pix_format *fmt) +{ + enum v4l2_colorspace colorspace; + + if (fmt->pixelformat == V4L2_PIX_FMT_JPEG) + colorspace = V4L2_COLORSPACE_JPEG; + else if (fmt->width <= 720 && fmt->height <= 576) + colorspace = V4L2_COLORSPACE_SMPTE170M; + else + colorspace = V4L2_COLORSPACE_REC709; + + fmt->colorspace = colorspace; + fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT; + fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + fmt->quantization = V4L2_QUANTIZATION_DEFAULT; +} + static int coda_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { @@ -648,16 +667,8 @@ static int coda_try_fmt_vid_out(struct file *file, void *priv, if (ret < 0) return ret; - switch (f->fmt.pix.colorspace) { - case V4L2_COLORSPACE_REC709: - case V4L2_COLORSPACE_JPEG: - break; - default: - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG) - f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; - else - f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; - } + if (f->fmt.pix.colorspace == V4L2_COLORSPACE_DEFAULT) + coda_set_default_colorspace(&f->fmt.pix); q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); codec = coda_find_codec(dev, f->fmt.pix.pixelformat, q_data_dst->fourcc); @@ -772,6 +783,9 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv, return ret; ctx->colorspace = f->fmt.pix.colorspace; + ctx->xfer_func = f->fmt.pix.xfer_func; + ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc; + ctx->quantization = f->fmt.pix.quantization; memset(&f_cap, 0, sizeof(f_cap)); f_cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -1282,7 +1296,13 @@ static void set_default_params(struct coda_ctx *ctx) csize = coda_estimate_sizeimage(ctx, usize, max_w, max_h); ctx->params.codec_mode = ctx->codec->mode; - ctx->colorspace = V4L2_COLORSPACE_REC709; + if (ctx->cvd->src_formats[0] == V4L2_PIX_FMT_JPEG) + ctx->colorspace = V4L2_COLORSPACE_JPEG; + else + ctx->colorspace = V4L2_COLORSPACE_REC709; + ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT; + ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + ctx->quantization = V4L2_QUANTIZATION_DEFAULT; ctx->params.framerate = 30; /* Default formats for output and input queues */ @@ -2063,8 +2083,7 @@ static int coda_hw_init(struct coda_dev *dev) if (ret) goto err_clk_ahb; - if (dev->rstc) - reset_control_reset(dev->rstc); + reset_control_reset(dev->rstc); /* * Copy the first CODA_ISRAM_SIZE in the internal SRAM. @@ -2448,13 +2467,8 @@ static int coda_probe(struct platform_device *pdev) dev->rstc = devm_reset_control_get_optional(&pdev->dev, NULL); if (IS_ERR(dev->rstc)) { ret = PTR_ERR(dev->rstc); - if (ret == -ENOENT || ret == -ENOTSUPP) { - dev->rstc = NULL; - } else { - dev_err(&pdev->dev, "failed get reset control: %d\n", - ret); - return ret; - } + dev_err(&pdev->dev, "failed get reset control: %d\n", ret); + return ret; } /* Get IRAM pool from device tree or platform data */ diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h index 20222befb9b2..308116d855e6 100644 --- a/drivers/media/platform/coda/coda.h +++ b/drivers/media/platform/coda/coda.h @@ -206,6 +206,9 @@ struct coda_ctx { enum coda_inst_type inst_type; const struct coda_codec *codec; enum v4l2_colorspace colorspace; + enum v4l2_xfer_func xfer_func; + enum v4l2_ycbcr_encoding ycbcr_enc; + enum v4l2_quantization quantization; struct coda_params params; struct v4l2_ctrl_handler ctrls; struct v4l2_fh fh; diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 44f702752d3a..128e92d1dd5a 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -513,7 +513,7 @@ static int vpif_update_std_info(struct channel_obj *ch) if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER) common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8; else - common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P; + common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_NV16; common->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -917,8 +917,8 @@ static int vpif_enum_fmt_vid_cap(struct file *file, void *priv, fmt->pixelformat = V4L2_PIX_FMT_SBGGR8; } else { fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(fmt->description, "YCbCr4:2:2 YC Planar"); - fmt->pixelformat = V4L2_PIX_FMT_YUV422P; + strcpy(fmt->description, "YCbCr4:2:2 Semi-Planar"); + fmt->pixelformat = V4L2_PIX_FMT_NV16; } return 0; } @@ -946,8 +946,8 @@ static int vpif_try_fmt_vid_cap(struct file *file, void *priv, if (pixfmt->pixelformat != V4L2_PIX_FMT_SBGGR8) pixfmt->pixelformat = V4L2_PIX_FMT_SBGGR8; } else { - if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) - pixfmt->pixelformat = V4L2_PIX_FMT_YUV422P; + if (pixfmt->pixelformat != V4L2_PIX_FMT_NV16) + pixfmt->pixelformat = V4L2_PIX_FMT_NV16; } common->fmt.fmt.pix.pixelformat = pixfmt->pixelformat; diff --git a/drivers/media/platform/exynos4-is/Kconfig b/drivers/media/platform/exynos4-is/Kconfig index 57d42c6172c5..c480efb755f5 100644 --- a/drivers/media/platform/exynos4-is/Kconfig +++ b/drivers/media/platform/exynos4-is/Kconfig @@ -4,6 +4,7 @@ config VIDEO_SAMSUNG_EXYNOS4_IS depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST depends on OF && COMMON_CLK + select V4L2_FWNODE help Say Y here to enable camera host interface devices for Samsung S5P and EXYNOS SoC series. @@ -32,6 +33,7 @@ config VIDEO_S5P_MIPI_CSIS tristate "S5P/EXYNOS MIPI-CSI2 receiver (MIPI-CSIS) driver" depends on REGULATOR select GENERIC_PHY + select V4L2_FWNODE help This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC MIPI-CSI2 receiver (MIPI-CSIS) devices. diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index 8a7cd07dbe28..db60a63c0768 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -1277,6 +1277,7 @@ static int fimc_cap_g_selection(struct file *file, void *fh, case V4L2_SEL_TGT_COMPOSE_DEFAULT: case V4L2_SEL_TGT_COMPOSE_BOUNDS: f = &ctx->d_frame; + /* fall through */ case V4L2_SEL_TGT_CROP_BOUNDS: case V4L2_SEL_TGT_CROP_DEFAULT: s->r.left = 0; @@ -1287,6 +1288,7 @@ static int fimc_cap_g_selection(struct file *file, void *fh, case V4L2_SEL_TGT_COMPOSE: f = &ctx->d_frame; + /* fall through */ case V4L2_SEL_TGT_CROP: s->r.left = f->offs_h; s->r.top = f->offs_v; @@ -1610,6 +1612,7 @@ static int fimc_subdev_get_selection(struct v4l2_subdev *sd, switch (sel->target) { case V4L2_SEL_TGT_COMPOSE_BOUNDS: f = &ctx->d_frame; + /* fall through */ case V4L2_SEL_TGT_CROP_BOUNDS: r->width = f->o_width; r->height = f->o_height; diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index e82450e90a67..7d1cf78846c4 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -29,7 +29,7 @@ #include <linux/slab.h> #include <media/v4l2-async.h> #include <media/v4l2-ctrls.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include <media/media-device.h> #include <media/drv-intf/exynos-fimc.h> @@ -388,7 +388,7 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, { struct fimc_source_info *pd = &fmd->sensor[index].pdata; struct device_node *rem, *ep, *np; - struct v4l2_of_endpoint endpoint; + struct v4l2_fwnode_endpoint endpoint; int ret; /* Assume here a port node can have only one endpoint node. */ @@ -396,7 +396,7 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, if (!ep) return 0; - ret = v4l2_of_parse_endpoint(ep, &endpoint); + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &endpoint); if (ret) { of_node_put(ep); return ret; @@ -453,8 +453,8 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, return -EINVAL; } - fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_OF; - fmd->sensor[index].asd.match.of.node = rem; + fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_FWNODE; + fmd->sensor[index].asd.match.fwnode.fwnode = of_fwnode_handle(rem); fmd->async_subdevs[index] = &fmd->sensor[index].asd; fmd->num_sensors++; @@ -1361,7 +1361,8 @@ static int subdev_notifier_bound(struct v4l2_async_notifier *notifier, /* Find platform data for this sensor subdev */ for (i = 0; i < ARRAY_SIZE(fmd->sensor); i++) - if (fmd->sensor[i].asd.match.of.node == subdev->dev->of_node) + if (fmd->sensor[i].asd.match.fwnode.fwnode == + of_fwnode_handle(subdev->dev->of_node)) si = &fmd->sensor[i]; if (si == NULL) diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index f819b29efc38..98c89873c2dc 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -30,7 +30,7 @@ #include <linux/spinlock.h> #include <linux/videodev2.h> #include <media/drv-intf/exynos-fimc.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include <media/v4l2-subdev.h> #include "mipi-csis.h" @@ -718,7 +718,7 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, struct csis_state *state) { struct device_node *node = pdev->dev.of_node; - struct v4l2_of_endpoint endpoint; + struct v4l2_fwnode_endpoint endpoint; int ret; if (of_property_read_u32(node, "clock-frequency", @@ -735,7 +735,7 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, return -EINVAL; } /* Get port node and validate MIPI-CSI channel id. */ - ret = v4l2_of_parse_endpoint(node, &endpoint); + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(node), &endpoint); if (ret) goto err; diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index a8bda6679422..8cac2f202099 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -393,6 +393,7 @@ static int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime) dma_free_coherent(cam->dev, cam->dma_buf_size, cam->dma_bufs[0], cam->dma_handles[0]); cam->nbufs = 0; + /* fall-through */ case 0: cam_err(cam, "Insufficient DMA buffers, cannot operate\n"); return -ENOMEM; diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c index a60b538686ea..843510979ad8 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c @@ -278,7 +278,7 @@ static void mtk_vdec_flush_decoder(struct mtk_vcodec_ctx *ctx) clean_free_buffer(ctx); } -static void mtk_vdec_pic_info_update(struct mtk_vcodec_ctx *ctx) +static int mtk_vdec_pic_info_update(struct mtk_vcodec_ctx *ctx) { unsigned int dpbsize = 0; int ret; @@ -288,7 +288,7 @@ static void mtk_vdec_pic_info_update(struct mtk_vcodec_ctx *ctx) &ctx->last_decoded_picinfo)) { mtk_v4l2_err("[%d]Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR", ctx->id); - return; + return -EINVAL; } if (ctx->last_decoded_picinfo.pic_w == 0 || @@ -296,12 +296,12 @@ static void mtk_vdec_pic_info_update(struct mtk_vcodec_ctx *ctx) ctx->last_decoded_picinfo.buf_w == 0 || ctx->last_decoded_picinfo.buf_h == 0) { mtk_v4l2_err("Cannot get correct pic info"); - return; + return -EINVAL; } if ((ctx->last_decoded_picinfo.pic_w == ctx->picinfo.pic_w) || (ctx->last_decoded_picinfo.pic_h == ctx->picinfo.pic_h)) - return; + return 0; mtk_v4l2_debug(1, "[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)", @@ -316,6 +316,8 @@ static void mtk_vdec_pic_info_update(struct mtk_vcodec_ctx *ctx) mtk_v4l2_err("Incorrect dpb size, ret=%d", ret); ctx->dpb_size = dpbsize; + + return ret; } static void mtk_vdec_worker(struct work_struct *work) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 0d984a28a003..9df64c189883 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -55,6 +55,7 @@ #include <linux/module.h> #include <linux/omap-iommu.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> #include <linux/sched.h> @@ -63,9 +64,9 @@ #include <asm/dma-iommu.h> #include <media/v4l2-common.h> +#include <media/v4l2-fwnode.h> #include <media/v4l2-device.h> #include <media/v4l2-mc.h> -#include <media/v4l2-of.h> #include "isp.h" #include "ispreg.h" @@ -2007,20 +2008,20 @@ enum isp_of_phy { ISP_OF_PHY_CSIPHY2, }; -static int isp_of_parse_node(struct device *dev, struct device_node *node, - struct isp_async_subdev *isd) +static int isp_fwnode_parse(struct device *dev, struct fwnode_handle *fwnode, + struct isp_async_subdev *isd) { struct isp_bus_cfg *buscfg = &isd->bus; - struct v4l2_of_endpoint vep; + struct v4l2_fwnode_endpoint vep; unsigned int i; int ret; - ret = v4l2_of_parse_endpoint(node, &vep); + ret = v4l2_fwnode_endpoint_parse(fwnode, &vep); if (ret) return ret; - dev_dbg(dev, "parsing endpoint %s, interface %u\n", node->full_name, - vep.base.port); + dev_dbg(dev, "parsing endpoint %s, interface %u\n", + to_of_node(fwnode)->full_name, vep.base.port); switch (vep.base.port) { case ISP_OF_PHY_PARALLEL: @@ -2077,18 +2078,18 @@ static int isp_of_parse_node(struct device *dev, struct device_node *node, break; default: - dev_warn(dev, "%s: invalid interface %u\n", node->full_name, - vep.base.port); + dev_warn(dev, "%s: invalid interface %u\n", + to_of_node(fwnode)->full_name, vep.base.port); break; } return 0; } -static int isp_of_parse_nodes(struct device *dev, - struct v4l2_async_notifier *notifier) +static int isp_fwnodes_parse(struct device *dev, + struct v4l2_async_notifier *notifier) { - struct device_node *node = NULL; + struct fwnode_handle *fwnode = NULL; notifier->subdevs = devm_kcalloc( dev, ISP_MAX_SUBDEVS, sizeof(*notifier->subdevs), GFP_KERNEL); @@ -2096,7 +2097,8 @@ static int isp_of_parse_nodes(struct device *dev, return -ENOMEM; while (notifier->num_subdevs < ISP_MAX_SUBDEVS && - (node = of_graph_get_next_endpoint(dev->of_node, node))) { + (fwnode = fwnode_graph_get_next_endpoint( + of_fwnode_handle(dev->of_node), fwnode))) { struct isp_async_subdev *isd; isd = devm_kzalloc(dev, sizeof(*isd), GFP_KERNEL); @@ -2105,23 +2107,24 @@ static int isp_of_parse_nodes(struct device *dev, notifier->subdevs[notifier->num_subdevs] = &isd->asd; - if (isp_of_parse_node(dev, node, isd)) + if (isp_fwnode_parse(dev, fwnode, isd)) goto error; - isd->asd.match.of.node = of_graph_get_remote_port_parent(node); - if (!isd->asd.match.of.node) { + isd->asd.match.fwnode.fwnode = + fwnode_graph_get_remote_port_parent(fwnode); + if (!isd->asd.match.fwnode.fwnode) { dev_warn(dev, "bad remote port parent\n"); goto error; } - isd->asd.match_type = V4L2_ASYNC_MATCH_OF; + isd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; notifier->num_subdevs++; } return notifier->num_subdevs; error: - of_node_put(node); + fwnode_handle_put(fwnode); return -EINVAL; } @@ -2192,8 +2195,8 @@ static int isp_probe(struct platform_device *pdev) return -ENOMEM; } - ret = of_property_read_u32(pdev->dev.of_node, "ti,phy-type", - &isp->phy_type); + ret = fwnode_property_read_u32(of_fwnode_handle(pdev->dev.of_node), + "ti,phy-type", &isp->phy_type); if (ret) return ret; @@ -2202,12 +2205,12 @@ static int isp_probe(struct platform_device *pdev) if (IS_ERR(isp->syscon)) return PTR_ERR(isp->syscon); - ret = of_property_read_u32_index(pdev->dev.of_node, "syscon", 1, - &isp->syscon_offset); + ret = of_property_read_u32_index(pdev->dev.of_node, + "syscon", 1, &isp->syscon_offset); if (ret) return ret; - ret = isp_of_parse_nodes(&pdev->dev, &isp->notifier); + ret = isp_fwnodes_parse(&pdev->dev, &isp->notifier); if (ret < 0) return ret; diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c index 929006f65cc7..399095170b6e 100644 --- a/drivers/media/platform/pxa_camera.c +++ b/drivers/media/platform/pxa_camera.c @@ -25,6 +25,7 @@ #include <linux/mm.h> #include <linux/moduleparam.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <linux/time.h> #include <linux/platform_device.h> #include <linux/clk.h> @@ -37,9 +38,11 @@ #include <media/v4l2-async.h> #include <media/v4l2-clk.h> #include <media/v4l2-common.h> +#include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> +#include <media/v4l2-event.h> #include <media/v4l2-ioctl.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include <media/videobuf2-dma-sg.h> @@ -345,6 +348,36 @@ static const struct pxa_mbus_lookup mbus_fmt[] = { .layout = PXA_MBUS_LAYOUT_PACKED, }, }, { + .code = MEDIA_BUS_FMT_SGBRG8_1X8, + .fmt = { + .fourcc = V4L2_PIX_FMT_SGBRG8, + .name = "Bayer 8 GBRG", + .bits_per_sample = 8, + .packing = PXA_MBUS_PACKING_NONE, + .order = PXA_MBUS_ORDER_LE, + .layout = PXA_MBUS_LAYOUT_PACKED, + }, +}, { + .code = MEDIA_BUS_FMT_SGRBG8_1X8, + .fmt = { + .fourcc = V4L2_PIX_FMT_SGRBG8, + .name = "Bayer 8 GRBG", + .bits_per_sample = 8, + .packing = PXA_MBUS_PACKING_NONE, + .order = PXA_MBUS_ORDER_LE, + .layout = PXA_MBUS_LAYOUT_PACKED, + }, +}, { + .code = MEDIA_BUS_FMT_SRGGB8_1X8, + .fmt = { + .fourcc = V4L2_PIX_FMT_SRGGB8, + .name = "Bayer 8 RGGB", + .bits_per_sample = 8, + .packing = PXA_MBUS_PACKING_NONE, + .order = PXA_MBUS_ORDER_LE, + .layout = PXA_MBUS_LAYOUT_PACKED, + }, +}, { .code = MEDIA_BUS_FMT_SBGGR10_1X10, .fmt = { .fourcc = V4L2_PIX_FMT_SBGGR10, @@ -445,16 +478,6 @@ static const struct pxa_mbus_lookup mbus_fmt[] = { .layout = PXA_MBUS_LAYOUT_PACKED, }, }, { - .code = MEDIA_BUS_FMT_SGRBG8_1X8, - .fmt = { - .fourcc = V4L2_PIX_FMT_SGRBG8, - .name = "Bayer 8 GRBG", - .bits_per_sample = 8, - .packing = PXA_MBUS_PACKING_NONE, - .order = PXA_MBUS_ORDER_LE, - .layout = PXA_MBUS_LAYOUT_PACKED, - }, -}, { .code = MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, .fmt = { .fourcc = V4L2_PIX_FMT_SGRBG10DPCM8, @@ -555,6 +578,9 @@ static s32 pxa_mbus_bytes_per_line(u32 width, const struct pxa_mbus_pixelfmt *mf static s32 pxa_mbus_image_size(const struct pxa_mbus_pixelfmt *mf, u32 bytes_per_line, u32 height) { + if (mf->layout == PXA_MBUS_LAYOUT_PACKED) + return bytes_per_line * height; + switch (mf->packing) { case PXA_MBUS_PACKING_2X8_PADHI: return bytes_per_line * height * 2; @@ -1099,7 +1125,7 @@ static u32 mclk_get_divisor(struct platform_device *pdev, /* mclk <= ciclk / 4 (27.4.2) */ if (mclk > lcdclk / 4) { mclk = lcdclk / 4; - dev_warn(pcdev_to_dev(pcdev), + dev_warn(&pdev->dev, "Limiting master clock to %lu\n", mclk); } @@ -1110,7 +1136,7 @@ static u32 mclk_get_divisor(struct platform_device *pdev, if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) pcdev->mclk = lcdclk / (2 * (div + 1)); - dev_dbg(pcdev_to_dev(pcdev), "LCD clock %luHz, target freq %luHz, divisor %u\n", + dev_dbg(&pdev->dev, "LCD clock %luHz, target freq %luHz, divisor %u\n", lcdclk, mclk, div); return div; @@ -1291,6 +1317,7 @@ static void pxa_camera_setup_cicr(struct pxa_camera_dev *pcdev, * transformation. Note that UYVY is the only format that * should be used if pxa framebuffer Overlay2 is used. */ + /* fall through */ case V4L2_PIX_FMT_UYVY: case V4L2_PIX_FMT_VYUY: case V4L2_PIX_FMT_YUYV: @@ -2066,6 +2093,8 @@ static const struct v4l2_ioctl_ops pxa_camera_ioctl_ops = { .vidioc_g_register = pxac_vidioc_g_register, .vidioc_s_register = pxac_vidioc_s_register, #endif + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; static struct v4l2_clk_ops pxa_camera_mclk_ops = { @@ -2177,6 +2206,12 @@ static void pxa_camera_sensor_unbind(struct v4l2_async_notifier *notifier, pxa_dma_stop_channels(pcdev); pxa_camera_destroy_formats(pcdev); + + if (pcdev->mclk_clk) { + v4l2_clk_unregister(pcdev->mclk_clk); + pcdev->mclk_clk = NULL; + } + video_unregister_device(&pcdev->vdev); pcdev->sensor = NULL; @@ -2236,7 +2271,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev, { u32 mclk_rate; struct device_node *remote, *np = dev->of_node; - struct v4l2_of_endpoint ep; + struct v4l2_fwnode_endpoint ep; int err = of_property_read_u32(np, "clock-frequency", &mclk_rate); if (!err) { @@ -2250,7 +2285,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev, return -EINVAL; } - err = v4l2_of_parse_endpoint(np, &ep); + err = v4l2_fwnode_endpoint_parse(of_fwnode_handle(np), &ep); if (err) { dev_err(dev, "could not parse endpoint\n"); goto out; @@ -2287,10 +2322,10 @@ static int pxa_camera_pdata_from_dt(struct device *dev, if (ep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) pcdev->platform_flags |= PXA_CAMERA_PCLK_EN; - asd->match_type = V4L2_ASYNC_MATCH_OF; + asd->match_type = V4L2_ASYNC_MATCH_FWNODE; remote = of_graph_get_remote_port(np); if (remote) { - asd->match.of.node = remote; + asd->match.fwnode.fwnode = of_fwnode_handle(remote); of_node_put(remote); } else { dev_notice(dev, "no remote for %s\n", of_node_full_name(np)); @@ -2501,7 +2536,13 @@ static int pxa_camera_remove(struct platform_device *pdev) dma_release_channel(pcdev->dma_chans[1]); dma_release_channel(pcdev->dma_chans[2]); - v4l2_clk_unregister(pcdev->mclk_clk); + v4l2_async_notifier_unregister(&pcdev->notifier); + + if (pcdev->mclk_clk) { + v4l2_clk_unregister(pcdev->mclk_clk); + pcdev->mclk_clk = NULL; + } + v4l2_device_unregister(&pcdev->v4l2_dev); dev_info(&pdev->dev, "PXA Camera driver unloaded\n"); diff --git a/drivers/media/platform/rcar-vin/Kconfig b/drivers/media/platform/rcar-vin/Kconfig index 111d2a151f6a..af4c98b44d2e 100644 --- a/drivers/media/platform/rcar-vin/Kconfig +++ b/drivers/media/platform/rcar-vin/Kconfig @@ -3,6 +3,7 @@ config VIDEO_RCAR_VIN depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF && HAS_DMA && MEDIA_CONTROLLER depends on ARCH_RENESAS || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG + select V4L2_FWNODE ---help--- Support for Renesas R-Car Video Input (VIN) driver. Supports R-Car Gen2 SoCs. diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index 098a0b1cc10a..77dff047c41c 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -21,7 +21,7 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include "rcar-vin.h" @@ -31,6 +31,20 @@ #define notifier_to_vin(n) container_of(n, struct rvin_dev, notifier) +static int rvin_find_pad(struct v4l2_subdev *sd, int direction) +{ + unsigned int pad; + + if (sd->entity.num_pads <= 1) + return 0; + + for (pad = 0; pad < sd->entity.num_pads; pad++) + if (sd->entity.pads[pad].flags & direction) + return pad; + + return -EINVAL; +} + static bool rvin_mbus_supported(struct rvin_graph_entity *entity) { struct v4l2_subdev *sd = entity->subdev; @@ -39,6 +53,7 @@ static bool rvin_mbus_supported(struct rvin_graph_entity *entity) }; code.index = 0; + code.pad = entity->source_pad; while (!v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code)) { code.index++; switch (code.code) { @@ -86,14 +101,9 @@ static void rvin_digital_notify_unbind(struct v4l2_async_notifier *notifier, { struct rvin_dev *vin = notifier_to_vin(notifier); - if (vin->digital.subdev == subdev) { - vin_dbg(vin, "unbind digital subdev %s\n", subdev->name); - rvin_v4l2_remove(vin); - vin->digital.subdev = NULL; - return; - } - - vin_err(vin, "no entity for subdev %s to unbind\n", subdev->name); + vin_dbg(vin, "unbind digital subdev %s\n", subdev->name); + rvin_v4l2_remove(vin); + vin->digital.subdev = NULL; } static int rvin_digital_notify_bound(struct v4l2_async_notifier *notifier, @@ -101,27 +111,37 @@ static int rvin_digital_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_async_subdev *asd) { struct rvin_dev *vin = notifier_to_vin(notifier); + int ret; v4l2_set_subdev_hostdata(subdev, vin); - if (vin->digital.asd.match.of.node == subdev->dev->of_node) { - vin_dbg(vin, "bound digital subdev %s\n", subdev->name); - vin->digital.subdev = subdev; - return 0; - } + /* Find source and sink pad of remote subdevice */ - vin_err(vin, "no entity for subdev %s to bind\n", subdev->name); - return -EINVAL; + ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SOURCE); + if (ret < 0) + return ret; + vin->digital.source_pad = ret; + + ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SINK); + vin->digital.sink_pad = ret < 0 ? 0 : ret; + + vin->digital.subdev = subdev; + + vin_dbg(vin, "bound subdev %s source pad: %u sink pad: %u\n", + subdev->name, vin->digital.source_pad, + vin->digital.sink_pad); + + return 0; } static int rvin_digitial_parse_v4l2(struct rvin_dev *vin, struct device_node *ep, struct v4l2_mbus_config *mbus_cfg) { - struct v4l2_of_endpoint v4l2_ep; + struct v4l2_fwnode_endpoint v4l2_ep; int ret; - ret = v4l2_of_parse_endpoint(ep, &v4l2_ep); + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &v4l2_ep); if (ret) { vin_err(vin, "Could not parse v4l2 endpoint\n"); return -EINVAL; @@ -151,7 +171,7 @@ static int rvin_digital_graph_parse(struct rvin_dev *vin) struct device_node *ep, *np; int ret; - vin->digital.asd.match.of.node = NULL; + vin->digital.asd.match.fwnode.fwnode = NULL; vin->digital.subdev = NULL; /* @@ -175,8 +195,8 @@ static int rvin_digital_graph_parse(struct rvin_dev *vin) if (ret) return ret; - vin->digital.asd.match.of.node = np; - vin->digital.asd.match_type = V4L2_ASYNC_MATCH_OF; + vin->digital.asd.match.fwnode.fwnode = of_fwnode_handle(np); + vin->digital.asd.match_type = V4L2_ASYNC_MATCH_FWNODE; return 0; } @@ -190,7 +210,7 @@ static int rvin_digital_graph_init(struct rvin_dev *vin) if (ret) return ret; - if (!vin->digital.asd.match.of.node) { + if (!vin->digital.asd.match.fwnode.fwnode) { vin_dbg(vin, "No digital subdevice found\n"); return -ENODEV; } @@ -203,7 +223,7 @@ static int rvin_digital_graph_init(struct rvin_dev *vin) subdevs[0] = &vin->digital.asd; vin_dbg(vin, "Found digital subdevice %s\n", - of_node_full_name(subdevs[0]->match.of.node)); + of_node_full_name(to_of_node(subdevs[0]->match.fwnode.fwnode))); vin->notifier.num_subdevs = 1; vin->notifier.subdevs = subdevs; diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index 9ccd5ff55e19..b136844499f6 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -119,6 +119,15 @@ #define VNDMR2_FTEV (1 << 17) #define VNDMR2_VLV(n) ((n & 0xf) << 12) +struct rvin_buffer { + struct vb2_v4l2_buffer vb; + struct list_head list; +}; + +#define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \ + struct rvin_buffer, \ + vb)->list) + static void rvin_write(struct rvin_dev *vin, u32 value, u32 offset) { iowrite32(value, vin->base + offset); @@ -269,48 +278,6 @@ static int rvin_setup(struct rvin_dev *vin) return 0; } -static void rvin_capture_on(struct rvin_dev *vin) -{ - vin_dbg(vin, "Capture on in %s mode\n", - vin->continuous ? "continuous" : "single"); - - if (vin->continuous) - /* Continuous Frame Capture Mode */ - rvin_write(vin, VNFC_C_FRAME, VNFC_REG); - else - /* Single Frame Capture Mode */ - rvin_write(vin, VNFC_S_FRAME, VNFC_REG); -} - -static void rvin_capture_off(struct rvin_dev *vin) -{ - /* Set continuous & single transfer off */ - rvin_write(vin, 0, VNFC_REG); -} - -static int rvin_capture_start(struct rvin_dev *vin) -{ - int ret; - - rvin_crop_scale_comp(vin); - - ret = rvin_setup(vin); - if (ret) - return ret; - - rvin_capture_on(vin); - - return 0; -} - -static void rvin_capture_stop(struct rvin_dev *vin) -{ - rvin_capture_off(vin); - - /* Disable module */ - rvin_write(vin, rvin_read(vin, VNMC_REG) & ~VNMC_ME, VNMC_REG); -} - static void rvin_disable_interrupts(struct rvin_dev *vin) { rvin_write(vin, 0, VNIE_REG); @@ -377,6 +344,99 @@ static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t addr) rvin_write(vin, offset, VNMB_REG(slot)); } +/* Moves a buffer from the queue to the HW slots */ +static bool rvin_fill_hw_slot(struct rvin_dev *vin, int slot) +{ + struct rvin_buffer *buf; + struct vb2_v4l2_buffer *vbuf; + dma_addr_t phys_addr_top; + + if (vin->queue_buf[slot] != NULL) + return true; + + if (list_empty(&vin->buf_list)) + return false; + + vin_dbg(vin, "Filling HW slot: %d\n", slot); + + /* Keep track of buffer we give to HW */ + buf = list_entry(vin->buf_list.next, struct rvin_buffer, list); + vbuf = &buf->vb; + list_del_init(to_buf_list(vbuf)); + vin->queue_buf[slot] = vbuf; + + /* Setup DMA */ + phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); + rvin_set_slot_addr(vin, slot, phys_addr_top); + + return true; +} + +static bool rvin_fill_hw(struct rvin_dev *vin) +{ + int slot, limit; + + limit = vin->continuous ? HW_BUFFER_NUM : 1; + + for (slot = 0; slot < limit; slot++) + if (!rvin_fill_hw_slot(vin, slot)) + return false; + return true; +} + +static void rvin_capture_on(struct rvin_dev *vin) +{ + vin_dbg(vin, "Capture on in %s mode\n", + vin->continuous ? "continuous" : "single"); + + if (vin->continuous) + /* Continuous Frame Capture Mode */ + rvin_write(vin, VNFC_C_FRAME, VNFC_REG); + else + /* Single Frame Capture Mode */ + rvin_write(vin, VNFC_S_FRAME, VNFC_REG); +} + +static int rvin_capture_start(struct rvin_dev *vin) +{ + struct rvin_buffer *buf, *node; + int bufs, ret; + + /* Count number of free buffers */ + bufs = 0; + list_for_each_entry_safe(buf, node, &vin->buf_list, list) + bufs++; + + /* Continuous capture requires more buffers then there are HW slots */ + vin->continuous = bufs > HW_BUFFER_NUM; + + if (!rvin_fill_hw(vin)) { + vin_err(vin, "HW not ready to start, not enough buffers available\n"); + return -EINVAL; + } + + rvin_crop_scale_comp(vin); + + ret = rvin_setup(vin); + if (ret) + return ret; + + rvin_capture_on(vin); + + vin->state = RUNNING; + + return 0; +} + +static void rvin_capture_stop(struct rvin_dev *vin) +{ + /* Set continuous & single transfer off */ + rvin_write(vin, 0, VNFC_REG); + + /* Disable module */ + rvin_write(vin, rvin_read(vin, VNMC_REG) & ~VNMC_ME, VNMC_REG); +} + /* ----------------------------------------------------------------------------- * Crop and Scaling Gen2 */ @@ -839,61 +899,12 @@ void rvin_scale_try(struct rvin_dev *vin, struct v4l2_pix_format *pix, #define RVIN_TIMEOUT_MS 100 #define RVIN_RETRIES 10 -struct rvin_buffer { - struct vb2_v4l2_buffer vb; - struct list_head list; -}; - -#define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \ - struct rvin_buffer, \ - vb)->list) - -/* Moves a buffer from the queue to the HW slots */ -static bool rvin_fill_hw_slot(struct rvin_dev *vin, int slot) -{ - struct rvin_buffer *buf; - struct vb2_v4l2_buffer *vbuf; - dma_addr_t phys_addr_top; - - if (vin->queue_buf[slot] != NULL) - return true; - - if (list_empty(&vin->buf_list)) - return false; - - vin_dbg(vin, "Filling HW slot: %d\n", slot); - - /* Keep track of buffer we give to HW */ - buf = list_entry(vin->buf_list.next, struct rvin_buffer, list); - vbuf = &buf->vb; - list_del_init(to_buf_list(vbuf)); - vin->queue_buf[slot] = vbuf; - - /* Setup DMA */ - phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); - rvin_set_slot_addr(vin, slot, phys_addr_top); - - return true; -} - -static bool rvin_fill_hw(struct rvin_dev *vin) -{ - int slot, limit; - - limit = vin->continuous ? HW_BUFFER_NUM : 1; - - for (slot = 0; slot < limit; slot++) - if (!rvin_fill_hw_slot(vin, slot)) - return false; - return true; -} - static irqreturn_t rvin_irq(int irq, void *data) { struct rvin_dev *vin = data; u32 int_status, vnms; int slot; - unsigned int sequence, handled = 0; + unsigned int i, sequence, handled = 0; unsigned long flags; spin_lock_irqsave(&vin->qlock, flags); @@ -955,8 +966,20 @@ static irqreturn_t rvin_irq(int irq, void *data) * the VnMBm registers. */ if (vin->continuous) { - rvin_capture_off(vin); + rvin_capture_stop(vin); vin_dbg(vin, "IRQ %02d: hw not ready stop\n", sequence); + + /* Maybe we can continue in single capture mode */ + for (i = 0; i < HW_BUFFER_NUM; i++) { + if (vin->queue_buf[i]) { + list_add(to_buf_list(vin->queue_buf[i]), + &vin->buf_list); + vin->queue_buf[i] = NULL; + } + } + + if (!list_empty(&vin->buf_list)) + rvin_capture_start(vin); } } else { /* @@ -1041,8 +1064,7 @@ static void rvin_buffer_queue(struct vb2_buffer *vb) * capturing if HW is ready to continue. */ if (vin->state == STALLED) - if (rvin_fill_hw(vin)) - rvin_capture_on(vin); + rvin_capture_start(vin); spin_unlock_irqrestore(&vin->qlock, flags); } @@ -1059,25 +1081,9 @@ static int rvin_start_streaming(struct vb2_queue *vq, unsigned int count) spin_lock_irqsave(&vin->qlock, flags); - vin->state = RUNNING; vin->sequence = 0; - /* Continuous capture requires more buffers then there are HW slots */ - vin->continuous = count > HW_BUFFER_NUM; - - /* - * This should never happen but if we don't have enough - * buffers for HW bail out - */ - if (!rvin_fill_hw(vin)) { - vin_err(vin, "HW not ready to start, not enough buffers available\n"); - ret = -EINVAL; - goto out; - } - ret = rvin_capture_start(vin); -out: - /* Return all buffers if something went wrong */ if (ret) { return_all_buffers(vin, VB2_BUF_STATE_QUEUED); v4l2_subdev_call(sd, video, s_stream, 0); @@ -1183,7 +1189,7 @@ int rvin_dma_probe(struct rvin_dev *vin, int irq) q->ops = &rvin_qops; q->mem_ops = &vb2_dma_contig_memops; q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->min_buffers_needed = 2; + q->min_buffers_needed = 1; q->dev = vin->dev; ret = vb2_queue_init(q); diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c index 2bbe6d495fa6..dd37ea811680 100644 --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c @@ -111,7 +111,7 @@ static int rvin_reset_format(struct rvin_dev *vin) struct v4l2_mbus_framefmt *mf = &fmt.format; int ret; - fmt.pad = vin->src_pad_idx; + fmt.pad = vin->digital.source_pad; ret = v4l2_subdev_call(vin_to_source(vin), pad, get_fmt, NULL, &fmt); if (ret) @@ -151,6 +151,9 @@ static int rvin_reset_format(struct rvin_dev *vin) rvin_reset_crop_compose(vin); + vin->format.bytesperline = rvin_format_bytesperline(&vin->format); + vin->format.sizeimage = rvin_format_sizeimage(&vin->format); + return 0; } @@ -175,7 +178,7 @@ static int __rvin_try_format_source(struct rvin_dev *vin, if (pad_cfg == NULL) return -ENOMEM; - format.pad = vin->src_pad_idx; + format.pad = vin->digital.source_pad; field = pix->field; @@ -203,8 +206,8 @@ static int __rvin_try_format(struct rvin_dev *vin, struct v4l2_pix_format *pix, struct rvin_source_fmt *source) { - const struct rvin_video_format *info; u32 rwidth, rheight, walign; + int ret; /* Requested */ rwidth = pix->width; @@ -214,17 +217,11 @@ static int __rvin_try_format(struct rvin_dev *vin, if (pix->field == V4L2_FIELD_ANY) pix->field = vin->format.field; - /* - * Retrieve format information and select the current format if the - * requested format isn't supported. - */ - info = rvin_format_from_pixel(pix->pixelformat); - if (!info) { - vin_dbg(vin, "Format %x not found, keeping %x\n", - pix->pixelformat, vin->format.pixelformat); - *pix = vin->format; - pix->width = rwidth; - pix->height = rheight; + /* If requested format is not supported fallback to the default */ + if (!rvin_format_from_pixel(pix->pixelformat)) { + vin_dbg(vin, "Format 0x%x not found, using default 0x%x\n", + pix->pixelformat, RVIN_DEFAULT_FORMAT); + pix->pixelformat = RVIN_DEFAULT_FORMAT; } /* Always recalculate */ @@ -232,7 +229,9 @@ static int __rvin_try_format(struct rvin_dev *vin, pix->sizeimage = 0; /* Limit to source capabilities */ - __rvin_try_format_source(vin, which, pix, source); + ret = __rvin_try_format_source(vin, which, pix, source); + if (ret) + return ret; switch (pix->field) { case V4L2_FIELD_TOP: @@ -480,10 +479,14 @@ static int rvin_enum_input(struct file *file, void *priv, return ret; i->type = V4L2_INPUT_TYPE_CAMERA; - i->std = vin->vdev.tvnorms; - if (v4l2_subdev_has_op(sd, pad, dv_timings_cap)) + if (v4l2_subdev_has_op(sd, pad, dv_timings_cap)) { i->capabilities = V4L2_IN_CAP_DV_TIMINGS; + i->std = 0; + } else { + i->capabilities = V4L2_IN_CAP_STD; + i->std = vin->vdev.tvnorms; + } strlcpy(i->name, "Camera", sizeof(i->name)); @@ -547,14 +550,16 @@ static int rvin_enum_dv_timings(struct file *file, void *priv_fh, { struct rvin_dev *vin = video_drvdata(file); struct v4l2_subdev *sd = vin_to_source(vin); - int pad, ret; + int ret; + + if (timings->pad) + return -EINVAL; - pad = timings->pad; - timings->pad = vin->sink_pad_idx; + timings->pad = vin->digital.sink_pad; ret = v4l2_subdev_call(sd, pad, enum_dv_timings, timings); - timings->pad = pad; + timings->pad = 0; return ret; } @@ -570,12 +575,8 @@ static int rvin_s_dv_timings(struct file *file, void *priv_fh, if (ret) return ret; - vin->source.width = timings->bt.width; - vin->source.height = timings->bt.height; - vin->format.width = timings->bt.width; - vin->format.height = timings->bt.height; - - return 0; + /* Changing the timings will change the width/height */ + return rvin_reset_format(vin); } static int rvin_g_dv_timings(struct file *file, void *priv_fh, @@ -601,14 +602,16 @@ static int rvin_dv_timings_cap(struct file *file, void *priv_fh, { struct rvin_dev *vin = video_drvdata(file); struct v4l2_subdev *sd = vin_to_source(vin); - int pad, ret; + int ret; + + if (cap->pad) + return -EINVAL; - pad = cap->pad; - cap->pad = vin->sink_pad_idx; + cap->pad = vin->digital.sink_pad; ret = v4l2_subdev_call(sd, pad, dv_timings_cap, cap); - cap->pad = pad; + cap->pad = 0; return ret; } @@ -617,17 +620,16 @@ static int rvin_g_edid(struct file *file, void *fh, struct v4l2_edid *edid) { struct rvin_dev *vin = video_drvdata(file); struct v4l2_subdev *sd = vin_to_source(vin); - int input, ret; + int ret; if (edid->pad) return -EINVAL; - input = edid->pad; - edid->pad = vin->sink_pad_idx; + edid->pad = vin->digital.sink_pad; ret = v4l2_subdev_call(sd, pad, get_edid, edid); - edid->pad = input; + edid->pad = 0; return ret; } @@ -636,17 +638,16 @@ static int rvin_s_edid(struct file *file, void *fh, struct v4l2_edid *edid) { struct rvin_dev *vin = video_drvdata(file); struct v4l2_subdev *sd = vin_to_source(vin); - int input, ret; + int ret; if (edid->pad) return -EINVAL; - input = edid->pad; - edid->pad = vin->sink_pad_idx; + edid->pad = vin->digital.sink_pad; ret = v4l2_subdev_call(sd, pad, set_edid, edid); - edid->pad = input; + edid->pad = 0; return ret; } @@ -869,7 +870,7 @@ int rvin_v4l2_probe(struct rvin_dev *vin) { struct video_device *vdev = &vin->vdev; struct v4l2_subdev *sd = vin_to_source(vin); - int pad_idx, ret; + int ret; v4l2_set_subdev_hostdata(sd, vin); @@ -915,22 +916,6 @@ int rvin_v4l2_probe(struct rvin_dev *vin) vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; - vin->src_pad_idx = 0; - for (pad_idx = 0; pad_idx < sd->entity.num_pads; pad_idx++) - if (sd->entity.pads[pad_idx].flags == MEDIA_PAD_FL_SOURCE) - break; - if (pad_idx >= sd->entity.num_pads) - return -EINVAL; - - vin->src_pad_idx = pad_idx; - - vin->sink_pad_idx = 0; - for (pad_idx = 0; pad_idx < sd->entity.num_pads; pad_idx++) - if (sd->entity.pads[pad_idx].flags == MEDIA_PAD_FL_SINK) { - vin->sink_pad_idx = pad_idx; - break; - } - vin->format.pixelformat = RVIN_DEFAULT_FORMAT; rvin_reset_format(vin); diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h index 727e215c0871..9bfb5a7c4dc4 100644 --- a/drivers/media/platform/rcar-vin/rcar-vin.h +++ b/drivers/media/platform/rcar-vin/rcar-vin.h @@ -74,6 +74,8 @@ struct rvin_video_format { * @subdev: subdevice matched using async framework * @code: Media bus format from source * @mbus_cfg: Media bus format from DT + * @source_pad: source pad of remote subdevice + * @sink_pad: sink pad of remote subdevice */ struct rvin_graph_entity { struct v4l2_async_subdev asd; @@ -81,6 +83,9 @@ struct rvin_graph_entity { u32 code; struct v4l2_mbus_config mbus_cfg; + + unsigned int source_pad; + unsigned int sink_pad; }; /** @@ -91,8 +96,6 @@ struct rvin_graph_entity { * * @vdev: V4L2 video device associated with VIN * @v4l2_dev: V4L2 device - * @src_pad_idx: source pad index for media controller drivers - * @sink_pad_idx: sink pad index for media controller drivers * @ctrl_handler: V4L2 control handler * @notifier: V4L2 asynchronous subdevs notifier * @digital: entity in the DT for local digital subdevice @@ -121,8 +124,6 @@ struct rvin_dev { struct video_device vdev; struct v4l2_device v4l2_dev; - int src_pad_idx; - int sink_pad_idx; struct v4l2_ctrl_handler ctrl_handler; struct v4l2_async_notifier notifier; struct rvin_graph_entity digital; diff --git a/drivers/media/platform/s5p-cec/s5p_cec.c b/drivers/media/platform/s5p-cec/s5p_cec.c index 664937b61fa4..65a223e578ed 100644 --- a/drivers/media/platform/s5p-cec/s5p_cec.c +++ b/drivers/media/platform/s5p-cec/s5p_cec.c @@ -235,7 +235,7 @@ static int s5p_cec_probe(struct platform_device *pdev) platform_set_drvdata(pdev, cec); pm_runtime_enable(dev); - dev_dbg(dev, "successfuly probed\n"); + dev_dbg(dev, "successfully probed\n"); return 0; err_delete_adapter: diff --git a/drivers/media/platform/s5p-cec/s5p_cec.h b/drivers/media/platform/s5p-cec/s5p_cec.h index 7015845c1caa..8bcd8dc1aeb9 100644 --- a/drivers/media/platform/s5p-cec/s5p_cec.h +++ b/drivers/media/platform/s5p-cec/s5p_cec.h @@ -22,7 +22,6 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/timer.h> -#include <linux/version.h> #include <linux/workqueue.h> #include <media/cec.h> diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 52dc7941db65..1da2c94e1dca 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1099,10 +1099,10 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, struct s5p_jpeg_ctx *ctx) { int c, components = 0, notfound, n_dht = 0, n_dqt = 0; - unsigned int height, width, word, subsampling = 0, sos = 0, sof = 0, - sof_len = 0; - unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER], - dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER]; + unsigned int height = 0, width = 0, word, subsampling = 0; + unsigned int sos = 0, sof = 0, sof_len = 0; + unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER]; + unsigned int dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER]; long length; struct s5p_jpeg_buffer jpeg_buffer; diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c index 992d61a8b961..871da2a2a91c 100644 --- a/drivers/media/platform/sh_vou.c +++ b/drivers/media/platform/sh_vou.c @@ -229,6 +229,7 @@ static void sh_vou_stream_config(struct sh_vou_device *vou_dev) break; case V4L2_PIX_FMT_RGB565: dataswap ^= 1; + /* fall through */ case V4L2_PIX_FMT_RGB565X: row_coeff = 2; break; @@ -815,6 +816,7 @@ static u32 sh_vou_ntsc_mode(enum sh_vou_bus_fmt bus_fmt) default: pr_warn("%s(): Invalid bus-format code %d, using default 8-bit\n", __func__, bus_fmt); + /* fall through */ case SH_VOU_BUS_8BIT: return 1; case SH_VOU_BUS_16BIT: diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 3c9421f4d8e3..45a0429d75bb 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -23,6 +23,7 @@ #include <linux/list.h> #include <linux/module.h> #include <linux/mutex.h> +#include <linux/of_graph.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> @@ -36,7 +37,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-dev.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include <media/videobuf2-v4l2.h> /* Default to VGA resolution */ @@ -1512,8 +1513,8 @@ static int soc_of_bind(struct soc_camera_host *ici, if (!info) return -ENOMEM; - info->sasd.asd.match.of.node = remote; - info->sasd.asd.match_type = V4L2_ASYNC_MATCH_OF; + info->sasd.asd.match.fwnode.fwnode = of_fwnode_handle(remote); + info->sasd.asd.match_type = V4L2_ASYNC_MATCH_FWNODE; info->subdev = &info->sasd.asd; /* Or shall this be managed by the soc-camera device? */ diff --git a/drivers/media/platform/soc_camera/soc_mediabus.c b/drivers/media/platform/soc_camera/soc_mediabus.c index e3e665e1c503..57581f626f4c 100644 --- a/drivers/media/platform/soc_camera/soc_mediabus.c +++ b/drivers/media/platform/soc_camera/soc_mediabus.c @@ -494,6 +494,7 @@ unsigned int soc_mbus_config_compatible(const struct v4l2_mbus_config *cfg, V4L2_MBUS_HSYNC_ACTIVE_LOW); vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW); + /* fall through */ case V4L2_MBUS_BT656: pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING); diff --git a/drivers/media/platform/sti/cec/stih-cec.c b/drivers/media/platform/sti/cec/stih-cec.c index 39ff55145a82..6f9f03670b56 100644 --- a/drivers/media/platform/sti/cec/stih-cec.c +++ b/drivers/media/platform/sti/cec/stih-cec.c @@ -1,6 +1,6 @@ /* * STIH4xx CEC driver - * Copyright (C) STMicroelectronic SA 2016 + * Copyright (C) STMicroelectronics SA 2016 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -213,7 +213,8 @@ static int stih_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, for (i = 0; i < msg->len; i++) writeb(msg->msg[i], cec->regs + CEC_TX_DATA_BASE + i); - /* Start transmission, configure hardware to add start and stop bits + /* + * Start transmission, configure hardware to add start and stop bits * Signal free time is handled by the hardware */ writel(CEC_TX_AUTO_SOM_EN | CEC_TX_AUTO_EOM_EN | CEC_TX_START | @@ -353,7 +354,7 @@ static int stih_cec_probe(struct platform_device *pdev) cec->adap = cec_allocate_adapter(&sti_cec_adap_ops, cec, CEC_NAME, CEC_CAP_LOG_ADDRS | CEC_CAP_PASSTHROUGH | - CEC_CAP_TRANSMIT, 1); + CEC_CAP_TRANSMIT, CEC_MAX_LOG_ADDRS); ret = PTR_ERR_OR_ZERO(cec->adap); if (ret) return ret; diff --git a/drivers/media/platform/stm32/Makefile b/drivers/media/platform/stm32/Makefile new file mode 100644 index 000000000000..9b606a70985d --- /dev/null +++ b/drivers/media/platform/stm32/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_VIDEO_STM32_DCMI) += stm32-dcmi.o diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c new file mode 100644 index 000000000000..83d32a5d0f40 --- /dev/null +++ b/drivers/media/platform/stm32/stm32-dcmi.c @@ -0,0 +1,1404 @@ +/* + * Driver for STM32 Digital Camera Memory Interface + * + * Copyright (C) STMicroelectronics SA 2017 + * Authors: Yannick Fertre <yannick.fertre@st.com> + * Hugues Fruchet <hugues.fruchet@st.com> + * for STMicroelectronics. + * License terms: GNU General Public License (GPL), version 2 + * + * This driver is based on atmel_isi.c + * + */ + +#include <linux/clk.h> +#include <linux/completion.h> +#include <linux/delay.h> +#include <linux/dmaengine.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_graph.h> +#include <linux/platform_device.h> +#include <linux/reset.h> +#include <linux/videodev2.h> + +#include <media/v4l2-ctrls.h> +#include <media/v4l2-dev.h> +#include <media/v4l2-device.h> +#include <media/v4l2-event.h> +#include <media/v4l2-fwnode.h> +#include <media/v4l2-image-sizes.h> +#include <media/v4l2-ioctl.h> +#include <media/videobuf2-dma-contig.h> + +#define DRV_NAME "stm32-dcmi" + +/* Registers offset for DCMI */ +#define DCMI_CR 0x00 /* Control Register */ +#define DCMI_SR 0x04 /* Status Register */ +#define DCMI_RIS 0x08 /* Raw Interrupt Status register */ +#define DCMI_IER 0x0C /* Interrupt Enable Register */ +#define DCMI_MIS 0x10 /* Masked Interrupt Status register */ +#define DCMI_ICR 0x14 /* Interrupt Clear Register */ +#define DCMI_ESCR 0x18 /* Embedded Synchronization Code Register */ +#define DCMI_ESUR 0x1C /* Embedded Synchronization Unmask Register */ +#define DCMI_CWSTRT 0x20 /* Crop Window STaRT */ +#define DCMI_CWSIZE 0x24 /* Crop Window SIZE */ +#define DCMI_DR 0x28 /* Data Register */ +#define DCMI_IDR 0x2C /* IDentifier Register */ + +/* Bits definition for control register (DCMI_CR) */ +#define CR_CAPTURE BIT(0) +#define CR_CM BIT(1) +#define CR_CROP BIT(2) +#define CR_JPEG BIT(3) +#define CR_ESS BIT(4) +#define CR_PCKPOL BIT(5) +#define CR_HSPOL BIT(6) +#define CR_VSPOL BIT(7) +#define CR_FCRC_0 BIT(8) +#define CR_FCRC_1 BIT(9) +#define CR_EDM_0 BIT(10) +#define CR_EDM_1 BIT(11) +#define CR_ENABLE BIT(14) + +/* Bits definition for status register (DCMI_SR) */ +#define SR_HSYNC BIT(0) +#define SR_VSYNC BIT(1) +#define SR_FNE BIT(2) + +/* + * Bits definition for interrupt registers + * (DCMI_RIS, DCMI_IER, DCMI_MIS, DCMI_ICR) + */ +#define IT_FRAME BIT(0) +#define IT_OVR BIT(1) +#define IT_ERR BIT(2) +#define IT_VSYNC BIT(3) +#define IT_LINE BIT(4) + +enum state { + STOPPED = 0, + RUNNING, + STOPPING, +}; + +#define MIN_WIDTH 16U +#define MAX_WIDTH 2048U +#define MIN_HEIGHT 16U +#define MAX_HEIGHT 2048U + +#define TIMEOUT_MS 1000 + +struct dcmi_graph_entity { + struct device_node *node; + + struct v4l2_async_subdev asd; + struct v4l2_subdev *subdev; +}; + +struct dcmi_format { + u32 fourcc; + u32 mbus_code; + u8 bpp; +}; + +struct dcmi_buf { + struct vb2_v4l2_buffer vb; + bool prepared; + dma_addr_t paddr; + size_t size; + struct list_head list; +}; + +struct stm32_dcmi { + /* Protects the access of variables shared within the interrupt */ + spinlock_t irqlock; + struct device *dev; + void __iomem *regs; + struct resource *res; + struct reset_control *rstc; + int sequence; + struct list_head buffers; + struct dcmi_buf *active; + + struct v4l2_device v4l2_dev; + struct video_device *vdev; + struct v4l2_async_notifier notifier; + struct dcmi_graph_entity entity; + struct v4l2_format fmt; + + const struct dcmi_format **user_formats; + unsigned int num_user_formats; + const struct dcmi_format *current_fmt; + + /* Protect this data structure */ + struct mutex lock; + struct vb2_queue queue; + + struct v4l2_fwnode_bus_parallel bus; + struct completion complete; + struct clk *mclk; + enum state state; + struct dma_chan *dma_chan; + dma_cookie_t dma_cookie; + u32 misr; + int errors_count; + int buffers_count; +}; + +static inline struct stm32_dcmi *notifier_to_dcmi(struct v4l2_async_notifier *n) +{ + return container_of(n, struct stm32_dcmi, notifier); +} + +static inline u32 reg_read(void __iomem *base, u32 reg) +{ + return readl_relaxed(base + reg); +} + +static inline void reg_write(void __iomem *base, u32 reg, u32 val) +{ + writel_relaxed(val, base + reg); +} + +static inline void reg_set(void __iomem *base, u32 reg, u32 mask) +{ + reg_write(base, reg, reg_read(base, reg) | mask); +} + +static inline void reg_clear(void __iomem *base, u32 reg, u32 mask) +{ + reg_write(base, reg, reg_read(base, reg) & ~mask); +} + +static int dcmi_start_capture(struct stm32_dcmi *dcmi); + +static void dcmi_dma_callback(void *param) +{ + struct stm32_dcmi *dcmi = (struct stm32_dcmi *)param; + struct dma_chan *chan = dcmi->dma_chan; + struct dma_tx_state state; + enum dma_status status; + + spin_lock(&dcmi->irqlock); + + /* Check DMA status */ + status = dmaengine_tx_status(chan, dcmi->dma_cookie, &state); + + switch (status) { + case DMA_IN_PROGRESS: + dev_dbg(dcmi->dev, "%s: Received DMA_IN_PROGRESS\n", __func__); + break; + case DMA_PAUSED: + dev_err(dcmi->dev, "%s: Received DMA_PAUSED\n", __func__); + break; + case DMA_ERROR: + dev_err(dcmi->dev, "%s: Received DMA_ERROR\n", __func__); + break; + case DMA_COMPLETE: + dev_dbg(dcmi->dev, "%s: Received DMA_COMPLETE\n", __func__); + + if (dcmi->active) { + struct dcmi_buf *buf = dcmi->active; + struct vb2_v4l2_buffer *vbuf = &dcmi->active->vb; + + vbuf->sequence = dcmi->sequence++; + vbuf->field = V4L2_FIELD_NONE; + vbuf->vb2_buf.timestamp = ktime_get_ns(); + vb2_set_plane_payload(&vbuf->vb2_buf, 0, buf->size); + vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE); + dev_dbg(dcmi->dev, "buffer[%d] done seq=%d\n", + vbuf->vb2_buf.index, vbuf->sequence); + + dcmi->buffers_count++; + dcmi->active = NULL; + } + + /* Restart a new DMA transfer with next buffer */ + if (dcmi->state == RUNNING) { + if (list_empty(&dcmi->buffers)) { + dev_err(dcmi->dev, "%s: No more buffer queued, cannot capture buffer", + __func__); + dcmi->errors_count++; + dcmi->active = NULL; + + spin_unlock(&dcmi->irqlock); + return; + } + + dcmi->active = list_entry(dcmi->buffers.next, + struct dcmi_buf, list); + + list_del_init(&dcmi->active->list); + + if (dcmi_start_capture(dcmi)) { + dev_err(dcmi->dev, "%s: Cannot restart capture on DMA complete", + __func__); + + spin_unlock(&dcmi->irqlock); + return; + } + + /* Enable capture */ + reg_set(dcmi->regs, DCMI_CR, CR_CAPTURE); + } + + break; + default: + dev_err(dcmi->dev, "%s: Received unknown status\n", __func__); + break; + } + + spin_unlock(&dcmi->irqlock); +} + +static int dcmi_start_dma(struct stm32_dcmi *dcmi, + struct dcmi_buf *buf) +{ + struct dma_async_tx_descriptor *desc = NULL; + struct dma_slave_config config; + int ret; + + memset(&config, 0, sizeof(config)); + + config.src_addr = (dma_addr_t)dcmi->res->start + DCMI_DR; + config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + config.dst_maxburst = 4; + + /* Configure DMA channel */ + ret = dmaengine_slave_config(dcmi->dma_chan, &config); + if (ret < 0) { + dev_err(dcmi->dev, "%s: DMA channel config failed (%d)\n", + __func__, ret); + return ret; + } + + /* Prepare a DMA transaction */ + desc = dmaengine_prep_slave_single(dcmi->dma_chan, buf->paddr, + buf->size, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); + if (!desc) { + dev_err(dcmi->dev, "%s: DMA dmaengine_prep_slave_single failed for buffer size %zu\n", + __func__, buf->size); + return -EINVAL; + } + + /* Set completion callback routine for notification */ + desc->callback = dcmi_dma_callback; + desc->callback_param = dcmi; + + /* Push current DMA transaction in the pending queue */ + dcmi->dma_cookie = dmaengine_submit(desc); + + dma_async_issue_pending(dcmi->dma_chan); + + return 0; +} + +static int dcmi_start_capture(struct stm32_dcmi *dcmi) +{ + int ret; + struct dcmi_buf *buf = dcmi->active; + + if (!buf) + return -EINVAL; + + ret = dcmi_start_dma(dcmi, buf); + if (ret) { + dcmi->errors_count++; + return ret; + } + + /* Enable capture */ + reg_set(dcmi->regs, DCMI_CR, CR_CAPTURE); + + return 0; +} + +static irqreturn_t dcmi_irq_thread(int irq, void *arg) +{ + struct stm32_dcmi *dcmi = arg; + + spin_lock(&dcmi->irqlock); + + /* Stop capture is required */ + if (dcmi->state == STOPPING) { + reg_clear(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR); + + dcmi->state = STOPPED; + + complete(&dcmi->complete); + + spin_unlock(&dcmi->irqlock); + return IRQ_HANDLED; + } + + if ((dcmi->misr & IT_OVR) || (dcmi->misr & IT_ERR)) { + /* + * An overflow or an error has been detected, + * stop current DMA transfert & restart it + */ + dev_warn(dcmi->dev, "%s: Overflow or error detected\n", + __func__); + + dcmi->errors_count++; + dmaengine_terminate_all(dcmi->dma_chan); + + reg_set(dcmi->regs, DCMI_ICR, IT_FRAME | IT_OVR | IT_ERR); + + dev_dbg(dcmi->dev, "Restarting capture after DCMI error\n"); + + if (dcmi_start_capture(dcmi)) { + dev_err(dcmi->dev, "%s: Cannot restart capture on overflow or error\n", + __func__); + + spin_unlock(&dcmi->irqlock); + return IRQ_HANDLED; + } + } + + spin_unlock(&dcmi->irqlock); + return IRQ_HANDLED; +} + +static irqreturn_t dcmi_irq_callback(int irq, void *arg) +{ + struct stm32_dcmi *dcmi = arg; + + spin_lock(&dcmi->irqlock); + + dcmi->misr = reg_read(dcmi->regs, DCMI_MIS); + + /* Clear interrupt */ + reg_set(dcmi->regs, DCMI_ICR, IT_FRAME | IT_OVR | IT_ERR); + + spin_unlock(&dcmi->irqlock); + + return IRQ_WAKE_THREAD; +} + +static int dcmi_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, + unsigned int *nplanes, + unsigned int sizes[], + struct device *alloc_devs[]) +{ + struct stm32_dcmi *dcmi = vb2_get_drv_priv(vq); + unsigned int size; + + size = dcmi->fmt.fmt.pix.sizeimage; + + /* Make sure the image size is large enough */ + if (*nplanes) + return sizes[0] < size ? -EINVAL : 0; + + *nplanes = 1; + sizes[0] = size; + + dcmi->active = NULL; + + dev_dbg(dcmi->dev, "Setup queue, count=%d, size=%d\n", + *nbuffers, size); + + return 0; +} + +static int dcmi_buf_init(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct dcmi_buf *buf = container_of(vbuf, struct dcmi_buf, vb); + + INIT_LIST_HEAD(&buf->list); + + return 0; +} + +static int dcmi_buf_prepare(struct vb2_buffer *vb) +{ + struct stm32_dcmi *dcmi = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct dcmi_buf *buf = container_of(vbuf, struct dcmi_buf, vb); + unsigned long size; + + size = dcmi->fmt.fmt.pix.sizeimage; + + if (vb2_plane_size(vb, 0) < size) { + dev_err(dcmi->dev, "%s data will not fit into plane (%lu < %lu)\n", + __func__, vb2_plane_size(vb, 0), size); + return -EINVAL; + } + + vb2_set_plane_payload(vb, 0, size); + + if (!buf->prepared) { + /* Get memory addresses */ + buf->paddr = + vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); + buf->size = vb2_plane_size(&buf->vb.vb2_buf, 0); + buf->prepared = true; + + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->size); + + dev_dbg(dcmi->dev, "buffer[%d] phy=0x%pad size=%zu\n", + vb->index, &buf->paddr, buf->size); + } + + return 0; +} + +static void dcmi_buf_queue(struct vb2_buffer *vb) +{ + struct stm32_dcmi *dcmi = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct dcmi_buf *buf = container_of(vbuf, struct dcmi_buf, vb); + unsigned long flags = 0; + + spin_lock_irqsave(&dcmi->irqlock, flags); + + if ((dcmi->state == RUNNING) && (!dcmi->active)) { + dcmi->active = buf; + + dev_dbg(dcmi->dev, "Starting capture on buffer[%d] queued\n", + buf->vb.vb2_buf.index); + + if (dcmi_start_capture(dcmi)) { + dev_err(dcmi->dev, "%s: Cannot restart capture on overflow or error\n", + __func__); + + spin_unlock_irqrestore(&dcmi->irqlock, flags); + return; + } + } else { + /* Enqueue to video buffers list */ + list_add_tail(&buf->list, &dcmi->buffers); + } + + spin_unlock_irqrestore(&dcmi->irqlock, flags); +} + +static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct stm32_dcmi *dcmi = vb2_get_drv_priv(vq); + struct dcmi_buf *buf, *node; + u32 val; + int ret; + + ret = clk_enable(dcmi->mclk); + if (ret) { + dev_err(dcmi->dev, "%s: Failed to start streaming, cannot enable clock", + __func__); + goto err_release_buffers; + } + + /* Enable stream on the sub device */ + ret = v4l2_subdev_call(dcmi->entity.subdev, video, s_stream, 1); + if (ret && ret != -ENOIOCTLCMD) { + dev_err(dcmi->dev, "%s: Failed to start streaming, subdev streamon error", + __func__); + goto err_disable_clock; + } + + spin_lock_irq(&dcmi->irqlock); + + val = reg_read(dcmi->regs, DCMI_CR); + + val &= ~(CR_PCKPOL | CR_HSPOL | CR_VSPOL | + CR_EDM_0 | CR_EDM_1 | CR_FCRC_0 | + CR_FCRC_1 | CR_JPEG | CR_ESS); + + /* Set bus width */ + switch (dcmi->bus.bus_width) { + case 14: + val &= CR_EDM_0 + CR_EDM_1; + break; + case 12: + val &= CR_EDM_1; + break; + case 10: + val &= CR_EDM_0; + break; + default: + /* Set bus width to 8 bits by default */ + break; + } + + /* Set vertical synchronization polarity */ + if (dcmi->bus.flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) + val |= CR_VSPOL; + + /* Set horizontal synchronization polarity */ + if (dcmi->bus.flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) + val |= CR_HSPOL; + + /* Set pixel clock polarity */ + if (dcmi->bus.flags & V4L2_MBUS_PCLK_SAMPLE_RISING) + val |= CR_PCKPOL; + + reg_write(dcmi->regs, DCMI_CR, val); + + /* Enable dcmi */ + reg_set(dcmi->regs, DCMI_CR, CR_ENABLE); + + dcmi->state = RUNNING; + + dcmi->sequence = 0; + dcmi->errors_count = 0; + dcmi->buffers_count = 0; + dcmi->active = NULL; + + /* + * Start transfer if at least one buffer has been queued, + * otherwise transfer is deferred at buffer queueing + */ + if (list_empty(&dcmi->buffers)) { + dev_dbg(dcmi->dev, "Start streaming is deferred to next buffer queueing\n"); + spin_unlock_irq(&dcmi->irqlock); + return 0; + } + + dcmi->active = list_entry(dcmi->buffers.next, struct dcmi_buf, list); + list_del_init(&dcmi->active->list); + + dev_dbg(dcmi->dev, "Start streaming, starting capture\n"); + + ret = dcmi_start_capture(dcmi); + if (ret) { + dev_err(dcmi->dev, "%s: Start streaming failed, cannot start capture", + __func__); + + spin_unlock_irq(&dcmi->irqlock); + goto err_subdev_streamoff; + } + + /* Enable interruptions */ + reg_set(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR); + + spin_unlock_irq(&dcmi->irqlock); + + return 0; + +err_subdev_streamoff: + v4l2_subdev_call(dcmi->entity.subdev, video, s_stream, 0); + +err_disable_clock: + clk_disable(dcmi->mclk); + +err_release_buffers: + spin_lock_irq(&dcmi->irqlock); + /* + * Return all buffers to vb2 in QUEUED state. + * This will give ownership back to userspace + */ + if (dcmi->active) { + buf = dcmi->active; + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); + dcmi->active = NULL; + } + list_for_each_entry_safe(buf, node, &dcmi->buffers, list) { + list_del_init(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); + } + spin_unlock_irq(&dcmi->irqlock); + + return ret; +} + +static void dcmi_stop_streaming(struct vb2_queue *vq) +{ + struct stm32_dcmi *dcmi = vb2_get_drv_priv(vq); + struct dcmi_buf *buf, *node; + unsigned long time_ms = msecs_to_jiffies(TIMEOUT_MS); + long timeout; + int ret; + + /* Disable stream on the sub device */ + ret = v4l2_subdev_call(dcmi->entity.subdev, video, s_stream, 0); + if (ret && ret != -ENOIOCTLCMD) + dev_err(dcmi->dev, "stream off failed in subdev\n"); + + dcmi->state = STOPPING; + + timeout = wait_for_completion_interruptible_timeout(&dcmi->complete, + time_ms); + + spin_lock_irq(&dcmi->irqlock); + + /* Disable interruptions */ + reg_clear(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR); + + /* Disable DCMI */ + reg_clear(dcmi->regs, DCMI_CR, CR_ENABLE); + + if (!timeout) { + dev_err(dcmi->dev, "Timeout during stop streaming\n"); + dcmi->state = STOPPED; + } + + /* Return all queued buffers to vb2 in ERROR state */ + if (dcmi->active) { + buf = dcmi->active; + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + dcmi->active = NULL; + } + list_for_each_entry_safe(buf, node, &dcmi->buffers, list) { + list_del_init(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } + + spin_unlock_irq(&dcmi->irqlock); + + /* Stop all pending DMA operations */ + dmaengine_terminate_all(dcmi->dma_chan); + + clk_disable(dcmi->mclk); + + dev_dbg(dcmi->dev, "Stop streaming, errors=%d buffers=%d\n", + dcmi->errors_count, dcmi->buffers_count); +} + +static struct vb2_ops dcmi_video_qops = { + .queue_setup = dcmi_queue_setup, + .buf_init = dcmi_buf_init, + .buf_prepare = dcmi_buf_prepare, + .buf_queue = dcmi_buf_queue, + .start_streaming = dcmi_start_streaming, + .stop_streaming = dcmi_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + +static int dcmi_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct stm32_dcmi *dcmi = video_drvdata(file); + + *fmt = dcmi->fmt; + + return 0; +} + +static const struct dcmi_format *find_format_by_fourcc(struct stm32_dcmi *dcmi, + unsigned int fourcc) +{ + unsigned int num_formats = dcmi->num_user_formats; + const struct dcmi_format *fmt; + unsigned int i; + + for (i = 0; i < num_formats; i++) { + fmt = dcmi->user_formats[i]; + if (fmt->fourcc == fourcc) + return fmt; + } + + return NULL; +} + +static int dcmi_try_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f, + const struct dcmi_format **current_fmt) +{ + const struct dcmi_format *dcmi_fmt; + struct v4l2_pix_format *pixfmt = &f->fmt.pix; + struct v4l2_subdev_pad_config pad_cfg; + struct v4l2_subdev_format format = { + .which = V4L2_SUBDEV_FORMAT_TRY, + }; + int ret; + + dcmi_fmt = find_format_by_fourcc(dcmi, pixfmt->pixelformat); + if (!dcmi_fmt) { + dcmi_fmt = dcmi->user_formats[dcmi->num_user_formats - 1]; + pixfmt->pixelformat = dcmi_fmt->fourcc; + } + + /* Limit to hardware capabilities */ + pixfmt->width = clamp(pixfmt->width, MIN_WIDTH, MAX_WIDTH); + pixfmt->height = clamp(pixfmt->height, MIN_HEIGHT, MAX_HEIGHT); + + v4l2_fill_mbus_format(&format.format, pixfmt, dcmi_fmt->mbus_code); + ret = v4l2_subdev_call(dcmi->entity.subdev, pad, set_fmt, + &pad_cfg, &format); + if (ret < 0) + return ret; + + v4l2_fill_pix_format(pixfmt, &format.format); + + pixfmt->field = V4L2_FIELD_NONE; + pixfmt->bytesperline = pixfmt->width * dcmi_fmt->bpp; + pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; + + if (current_fmt) + *current_fmt = dcmi_fmt; + + return 0; +} + +static int dcmi_set_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f) +{ + struct v4l2_subdev_format format = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + const struct dcmi_format *current_fmt; + int ret; + + ret = dcmi_try_fmt(dcmi, f, ¤t_fmt); + if (ret) + return ret; + + v4l2_fill_mbus_format(&format.format, &f->fmt.pix, + current_fmt->mbus_code); + ret = v4l2_subdev_call(dcmi->entity.subdev, pad, + set_fmt, NULL, &format); + if (ret < 0) + return ret; + + dcmi->fmt = *f; + dcmi->current_fmt = current_fmt; + + return 0; +} + +static int dcmi_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct stm32_dcmi *dcmi = video_drvdata(file); + + if (vb2_is_streaming(&dcmi->queue)) + return -EBUSY; + + return dcmi_set_fmt(dcmi, f); +} + +static int dcmi_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct stm32_dcmi *dcmi = video_drvdata(file); + + return dcmi_try_fmt(dcmi, f, NULL); +} + +static int dcmi_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct stm32_dcmi *dcmi = video_drvdata(file); + + if (f->index >= dcmi->num_user_formats) + return -EINVAL; + + f->pixelformat = dcmi->user_formats[f->index]->fourcc; + return 0; +} + +static int dcmi_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + strlcpy(cap->driver, DRV_NAME, sizeof(cap->driver)); + strlcpy(cap->card, "STM32 Camera Memory Interface", + sizeof(cap->card)); + strlcpy(cap->bus_info, "platform:dcmi", sizeof(cap->bus_info)); + return 0; +} + +static int dcmi_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + if (i->index != 0) + return -EINVAL; + + i->type = V4L2_INPUT_TYPE_CAMERA; + strlcpy(i->name, "Camera", sizeof(i->name)); + return 0; +} + +static int dcmi_g_input(struct file *file, void *priv, unsigned int *i) +{ + *i = 0; + return 0; +} + +static int dcmi_s_input(struct file *file, void *priv, unsigned int i) +{ + if (i > 0) + return -EINVAL; + return 0; +} + +static int dcmi_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fsize) +{ + struct stm32_dcmi *dcmi = video_drvdata(file); + const struct dcmi_format *dcmi_fmt; + struct v4l2_subdev_frame_size_enum fse = { + .index = fsize->index, + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + int ret; + + dcmi_fmt = find_format_by_fourcc(dcmi, fsize->pixel_format); + if (!dcmi_fmt) + return -EINVAL; + + fse.code = dcmi_fmt->mbus_code; + + ret = v4l2_subdev_call(dcmi->entity.subdev, pad, enum_frame_size, + NULL, &fse); + if (ret) + return ret; + + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = fse.max_width; + fsize->discrete.height = fse.max_height; + + return 0; +} + +static int dcmi_enum_frameintervals(struct file *file, void *fh, + struct v4l2_frmivalenum *fival) +{ + struct stm32_dcmi *dcmi = video_drvdata(file); + const struct dcmi_format *dcmi_fmt; + struct v4l2_subdev_frame_interval_enum fie = { + .index = fival->index, + .width = fival->width, + .height = fival->height, + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + int ret; + + dcmi_fmt = find_format_by_fourcc(dcmi, fival->pixel_format); + if (!dcmi_fmt) + return -EINVAL; + + fie.code = dcmi_fmt->mbus_code; + + ret = v4l2_subdev_call(dcmi->entity.subdev, pad, + enum_frame_interval, NULL, &fie); + if (ret) + return ret; + + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; + fival->discrete = fie.interval; + + return 0; +} + +static const struct of_device_id stm32_dcmi_of_match[] = { + { .compatible = "st,stm32-dcmi"}, + { /* end node */ }, +}; +MODULE_DEVICE_TABLE(of, stm32_dcmi_of_match); + +static int dcmi_open(struct file *file) +{ + struct stm32_dcmi *dcmi = video_drvdata(file); + struct v4l2_subdev *sd = dcmi->entity.subdev; + int ret; + + if (mutex_lock_interruptible(&dcmi->lock)) + return -ERESTARTSYS; + + ret = v4l2_fh_open(file); + if (ret < 0) + goto unlock; + + if (!v4l2_fh_is_singular_file(file)) + goto fh_rel; + + ret = v4l2_subdev_call(sd, core, s_power, 1); + if (ret < 0 && ret != -ENOIOCTLCMD) + goto fh_rel; + + ret = dcmi_set_fmt(dcmi, &dcmi->fmt); + if (ret) + v4l2_subdev_call(sd, core, s_power, 0); +fh_rel: + if (ret) + v4l2_fh_release(file); +unlock: + mutex_unlock(&dcmi->lock); + return ret; +} + +static int dcmi_release(struct file *file) +{ + struct stm32_dcmi *dcmi = video_drvdata(file); + struct v4l2_subdev *sd = dcmi->entity.subdev; + bool fh_singular; + int ret; + + mutex_lock(&dcmi->lock); + + fh_singular = v4l2_fh_is_singular_file(file); + + ret = _vb2_fop_release(file, NULL); + + if (fh_singular) + v4l2_subdev_call(sd, core, s_power, 0); + + mutex_unlock(&dcmi->lock); + + return ret; +} + +static const struct v4l2_ioctl_ops dcmi_ioctl_ops = { + .vidioc_querycap = dcmi_querycap, + + .vidioc_try_fmt_vid_cap = dcmi_try_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = dcmi_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = dcmi_s_fmt_vid_cap, + .vidioc_enum_fmt_vid_cap = dcmi_enum_fmt_vid_cap, + + .vidioc_enum_input = dcmi_enum_input, + .vidioc_g_input = dcmi_g_input, + .vidioc_s_input = dcmi_s_input, + + .vidioc_enum_framesizes = dcmi_enum_framesizes, + .vidioc_enum_frameintervals = dcmi_enum_frameintervals, + + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static const struct v4l2_file_operations dcmi_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = video_ioctl2, + .open = dcmi_open, + .release = dcmi_release, + .poll = vb2_fop_poll, + .mmap = vb2_fop_mmap, +#ifndef CONFIG_MMU + .get_unmapped_area = vb2_fop_get_unmapped_area, +#endif + .read = vb2_fop_read, +}; + +static int dcmi_set_default_fmt(struct stm32_dcmi *dcmi) +{ + struct v4l2_format f = { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .fmt.pix = { + .width = CIF_WIDTH, + .height = CIF_HEIGHT, + .field = V4L2_FIELD_NONE, + .pixelformat = dcmi->user_formats[0]->fourcc, + }, + }; + int ret; + + ret = dcmi_try_fmt(dcmi, &f, NULL); + if (ret) + return ret; + dcmi->current_fmt = dcmi->user_formats[0]; + dcmi->fmt = f; + return 0; +} + +static const struct dcmi_format dcmi_formats[] = { + { + .fourcc = V4L2_PIX_FMT_RGB565, + .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE, + .bpp = 2, + }, { + .fourcc = V4L2_PIX_FMT_YUYV, + .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, + .bpp = 2, + }, { + .fourcc = V4L2_PIX_FMT_UYVY, + .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, + .bpp = 2, + }, +}; + +static int dcmi_formats_init(struct stm32_dcmi *dcmi) +{ + const struct dcmi_format *dcmi_fmts[ARRAY_SIZE(dcmi_formats)]; + unsigned int num_fmts = 0, i, j; + struct v4l2_subdev *subdev = dcmi->entity.subdev; + struct v4l2_subdev_mbus_code_enum mbus_code = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + + while (!v4l2_subdev_call(subdev, pad, enum_mbus_code, + NULL, &mbus_code)) { + for (i = 0; i < ARRAY_SIZE(dcmi_formats); i++) { + if (dcmi_formats[i].mbus_code != mbus_code.code) + continue; + + /* Code supported, have we got this fourcc yet? */ + for (j = 0; j < num_fmts; j++) + if (dcmi_fmts[j]->fourcc == + dcmi_formats[i].fourcc) + /* Already available */ + break; + if (j == num_fmts) + /* New */ + dcmi_fmts[num_fmts++] = dcmi_formats + i; + } + mbus_code.index++; + } + + if (!num_fmts) + return -ENXIO; + + dcmi->num_user_formats = num_fmts; + dcmi->user_formats = devm_kcalloc(dcmi->dev, + num_fmts, sizeof(struct dcmi_format *), + GFP_KERNEL); + if (!dcmi->user_formats) { + dev_err(dcmi->dev, "could not allocate memory\n"); + return -ENOMEM; + } + + memcpy(dcmi->user_formats, dcmi_fmts, + num_fmts * sizeof(struct dcmi_format *)); + dcmi->current_fmt = dcmi->user_formats[0]; + + return 0; +} + +static int dcmi_graph_notify_complete(struct v4l2_async_notifier *notifier) +{ + struct stm32_dcmi *dcmi = notifier_to_dcmi(notifier); + int ret; + + dcmi->vdev->ctrl_handler = dcmi->entity.subdev->ctrl_handler; + ret = dcmi_formats_init(dcmi); + if (ret) { + dev_err(dcmi->dev, "No supported mediabus format found\n"); + return ret; + } + + ret = dcmi_set_default_fmt(dcmi); + if (ret) { + dev_err(dcmi->dev, "Could not set default format\n"); + return ret; + } + + ret = video_register_device(dcmi->vdev, VFL_TYPE_GRABBER, -1); + if (ret) { + dev_err(dcmi->dev, "Failed to register video device\n"); + return ret; + } + + dev_dbg(dcmi->dev, "Device registered as %s\n", + video_device_node_name(dcmi->vdev)); + return 0; +} + +static void dcmi_graph_notify_unbind(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct stm32_dcmi *dcmi = notifier_to_dcmi(notifier); + + dev_dbg(dcmi->dev, "Removing %s\n", video_device_node_name(dcmi->vdev)); + + /* Checks internaly if vdev has been init or not */ + video_unregister_device(dcmi->vdev); +} + +static int dcmi_graph_notify_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd) +{ + struct stm32_dcmi *dcmi = notifier_to_dcmi(notifier); + + dev_dbg(dcmi->dev, "Subdev %s bound\n", subdev->name); + + dcmi->entity.subdev = subdev; + + return 0; +} + +static int dcmi_graph_parse(struct stm32_dcmi *dcmi, struct device_node *node) +{ + struct device_node *ep = NULL; + struct device_node *remote; + + while (1) { + ep = of_graph_get_next_endpoint(node, ep); + if (!ep) + return -EINVAL; + + remote = of_graph_get_remote_port_parent(ep); + if (!remote) { + of_node_put(ep); + return -EINVAL; + } + + /* Remote node to connect */ + dcmi->entity.node = remote; + dcmi->entity.asd.match_type = V4L2_ASYNC_MATCH_FWNODE; + dcmi->entity.asd.match.fwnode.fwnode = of_fwnode_handle(remote); + return 0; + } +} + +static int dcmi_graph_init(struct stm32_dcmi *dcmi) +{ + struct v4l2_async_subdev **subdevs = NULL; + int ret; + + /* Parse the graph to extract a list of subdevice DT nodes. */ + ret = dcmi_graph_parse(dcmi, dcmi->dev->of_node); + if (ret < 0) { + dev_err(dcmi->dev, "Graph parsing failed\n"); + return ret; + } + + /* Register the subdevices notifier. */ + subdevs = devm_kzalloc(dcmi->dev, sizeof(*subdevs), GFP_KERNEL); + if (!subdevs) { + of_node_put(dcmi->entity.node); + return -ENOMEM; + } + + subdevs[0] = &dcmi->entity.asd; + + dcmi->notifier.subdevs = subdevs; + dcmi->notifier.num_subdevs = 1; + dcmi->notifier.bound = dcmi_graph_notify_bound; + dcmi->notifier.unbind = dcmi_graph_notify_unbind; + dcmi->notifier.complete = dcmi_graph_notify_complete; + + ret = v4l2_async_notifier_register(&dcmi->v4l2_dev, &dcmi->notifier); + if (ret < 0) { + dev_err(dcmi->dev, "Notifier registration failed\n"); + of_node_put(dcmi->entity.node); + return ret; + } + + return 0; +} + +static int dcmi_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match = NULL; + struct v4l2_fwnode_endpoint ep; + struct stm32_dcmi *dcmi; + struct vb2_queue *q; + struct dma_chan *chan; + struct clk *mclk; + int irq; + int ret = 0; + + match = of_match_device(of_match_ptr(stm32_dcmi_of_match), &pdev->dev); + if (!match) { + dev_err(&pdev->dev, "Could not find a match in devicetree\n"); + return -ENODEV; + } + + dcmi = devm_kzalloc(&pdev->dev, sizeof(struct stm32_dcmi), GFP_KERNEL); + if (!dcmi) + return -ENOMEM; + + dcmi->rstc = devm_reset_control_get(&pdev->dev, NULL); + if (IS_ERR(dcmi->rstc)) { + dev_err(&pdev->dev, "Could not get reset control\n"); + return -ENODEV; + } + + /* Get bus characteristics from devicetree */ + np = of_graph_get_next_endpoint(np, NULL); + if (!np) { + dev_err(&pdev->dev, "Could not find the endpoint\n"); + of_node_put(np); + return -ENODEV; + } + + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(np), &ep); + if (ret) { + dev_err(&pdev->dev, "Could not parse the endpoint\n"); + of_node_put(np); + return -ENODEV; + } + + if (ep.bus_type == V4L2_MBUS_CSI2) { + dev_err(&pdev->dev, "CSI bus not supported\n"); + of_node_put(np); + return -ENODEV; + } + dcmi->bus.flags = ep.bus.parallel.flags; + dcmi->bus.bus_width = ep.bus.parallel.bus_width; + dcmi->bus.data_shift = ep.bus.parallel.data_shift; + + of_node_put(np); + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) { + dev_err(&pdev->dev, "Could not get irq\n"); + return -ENODEV; + } + + dcmi->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!dcmi->res) { + dev_err(&pdev->dev, "Could not get resource\n"); + return -ENODEV; + } + + dcmi->regs = devm_ioremap_resource(&pdev->dev, dcmi->res); + if (IS_ERR(dcmi->regs)) { + dev_err(&pdev->dev, "Could not map registers\n"); + return PTR_ERR(dcmi->regs); + } + + ret = devm_request_threaded_irq(&pdev->dev, irq, dcmi_irq_callback, + dcmi_irq_thread, IRQF_ONESHOT, + dev_name(&pdev->dev), dcmi); + if (ret) { + dev_err(&pdev->dev, "Unable to request irq %d\n", irq); + return -ENODEV; + } + + mclk = devm_clk_get(&pdev->dev, "mclk"); + if (IS_ERR(mclk)) { + dev_err(&pdev->dev, "Unable to get mclk\n"); + return PTR_ERR(mclk); + } + + chan = dma_request_slave_channel(&pdev->dev, "tx"); + if (!chan) { + dev_info(&pdev->dev, "Unable to request DMA channel, defer probing\n"); + return -EPROBE_DEFER; + } + + ret = clk_prepare(mclk); + if (ret) { + dev_err(&pdev->dev, "Unable to prepare mclk %p\n", mclk); + goto err_dma_release; + } + + spin_lock_init(&dcmi->irqlock); + mutex_init(&dcmi->lock); + init_completion(&dcmi->complete); + INIT_LIST_HEAD(&dcmi->buffers); + + dcmi->dev = &pdev->dev; + dcmi->mclk = mclk; + dcmi->state = STOPPED; + dcmi->dma_chan = chan; + + q = &dcmi->queue; + + /* Initialize the top-level structure */ + ret = v4l2_device_register(&pdev->dev, &dcmi->v4l2_dev); + if (ret) + goto err_clk_unprepare; + + dcmi->vdev = video_device_alloc(); + if (!dcmi->vdev) { + ret = -ENOMEM; + goto err_device_unregister; + } + + /* Video node */ + dcmi->vdev->fops = &dcmi_fops; + dcmi->vdev->v4l2_dev = &dcmi->v4l2_dev; + dcmi->vdev->queue = &dcmi->queue; + strlcpy(dcmi->vdev->name, KBUILD_MODNAME, sizeof(dcmi->vdev->name)); + dcmi->vdev->release = video_device_release; + dcmi->vdev->ioctl_ops = &dcmi_ioctl_ops; + dcmi->vdev->lock = &dcmi->lock; + dcmi->vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + video_set_drvdata(dcmi->vdev, dcmi); + + /* Buffer queue */ + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF; + q->lock = &dcmi->lock; + q->drv_priv = dcmi; + q->buf_struct_size = sizeof(struct dcmi_buf); + q->ops = &dcmi_video_qops; + q->mem_ops = &vb2_dma_contig_memops; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->min_buffers_needed = 2; + q->dev = &pdev->dev; + + ret = vb2_queue_init(q); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to initialize vb2 queue\n"); + goto err_device_release; + } + + ret = dcmi_graph_init(dcmi); + if (ret < 0) + goto err_device_release; + + /* Reset device */ + ret = reset_control_assert(dcmi->rstc); + if (ret) { + dev_err(&pdev->dev, "Failed to assert the reset line\n"); + goto err_device_release; + } + + usleep_range(3000, 5000); + + ret = reset_control_deassert(dcmi->rstc); + if (ret) { + dev_err(&pdev->dev, "Failed to deassert the reset line\n"); + goto err_device_release; + } + + dev_info(&pdev->dev, "Probe done\n"); + + platform_set_drvdata(pdev, dcmi); + return 0; + +err_device_release: + video_device_release(dcmi->vdev); +err_device_unregister: + v4l2_device_unregister(&dcmi->v4l2_dev); +err_clk_unprepare: + clk_unprepare(dcmi->mclk); +err_dma_release: + dma_release_channel(dcmi->dma_chan); + + return ret; +} + +static int dcmi_remove(struct platform_device *pdev) +{ + struct stm32_dcmi *dcmi = platform_get_drvdata(pdev); + + v4l2_async_notifier_unregister(&dcmi->notifier); + v4l2_device_unregister(&dcmi->v4l2_dev); + clk_unprepare(dcmi->mclk); + dma_release_channel(dcmi->dma_chan); + + return 0; +} + +static struct platform_driver stm32_dcmi_driver = { + .probe = dcmi_probe, + .remove = dcmi_remove, + .driver = { + .name = DRV_NAME, + .of_match_table = of_match_ptr(stm32_dcmi_of_match), + }, +}; + +module_platform_driver(stm32_dcmi_driver); + +MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>"); +MODULE_AUTHOR("Hugues Fruchet <hugues.fruchet@st.com>"); +MODULE_DESCRIPTION("STMicroelectronics STM32 Digital Camera Memory Interface driver"); +MODULE_LICENSE("GPL"); +MODULE_SUPPORTED_DEVICE("video"); diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c index 7a058b6e03d0..177faa36bc16 100644 --- a/drivers/media/platform/ti-vpe/cal.c +++ b/drivers/media/platform/ti-vpe/cal.c @@ -21,7 +21,7 @@ #include <linux/of_device.h> #include <linux/of_graph.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include <media/v4l2-async.h> #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> @@ -270,7 +270,7 @@ struct cal_ctx { struct video_device vdev; struct v4l2_async_notifier notifier; struct v4l2_subdev *sensor; - struct v4l2_of_endpoint endpoint; + struct v4l2_fwnode_endpoint endpoint; struct v4l2_async_subdev asd; struct v4l2_async_subdev *asd_list[1]; @@ -608,7 +608,8 @@ static void csi2_lane_config(struct cal_ctx *ctx) u32 val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)); u32 lane_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK; u32 polarity_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK; - struct v4l2_of_bus_mipi_csi2 *mipi_csi2 = &ctx->endpoint.bus.mipi_csi2; + struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 = + &ctx->endpoint.bus.mipi_csi2; int lane; set_field(&val, mipi_csi2->clock_lane + 1, lane_mask); @@ -1643,7 +1644,7 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst) struct platform_device *pdev = ctx->dev->pdev; struct device_node *ep_node, *port, *remote_ep, *sensor_node, *parent; - struct v4l2_of_endpoint *endpoint; + struct v4l2_fwnode_endpoint *endpoint; struct v4l2_async_subdev *asd; u32 regval = 0; int ret, index, found_port = 0, lane; @@ -1698,15 +1699,15 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst) ctx_dbg(3, ctx, "can't get remote parent\n"); goto cleanup_exit; } - asd->match_type = V4L2_ASYNC_MATCH_OF; - asd->match.of.node = sensor_node; + asd->match_type = V4L2_ASYNC_MATCH_FWNODE; + asd->match.fwnode.fwnode = of_fwnode_handle(sensor_node); remote_ep = of_parse_phandle(ep_node, "remote-endpoint", 0); if (!remote_ep) { ctx_dbg(3, ctx, "can't get remote-endpoint\n"); goto cleanup_exit; } - v4l2_of_parse_endpoint(remote_ep, endpoint); + v4l2_fwnode_endpoint_parse(of_fwnode_handle(remote_ep), endpoint); if (endpoint->bus_type != V4L2_MBUS_CSI2) { ctx_err(ctx, "Port:%d sub-device %s is not a CSI2 device\n", diff --git a/drivers/media/platform/xilinx/Kconfig b/drivers/media/platform/xilinx/Kconfig index 84bae795b70d..a5d21b7c6e0b 100644 --- a/drivers/media/platform/xilinx/Kconfig +++ b/drivers/media/platform/xilinx/Kconfig @@ -2,6 +2,7 @@ config VIDEO_XILINX tristate "Xilinx Video IP (EXPERIMENTAL)" depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF && HAS_DMA select VIDEOBUF2_DMA_CONTIG + select V4L2_FWNODE ---help--- Driver for Xilinx Video IP Pipelines diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c index feb3b2f1d874..ac4704388920 100644 --- a/drivers/media/platform/xilinx/xilinx-vipp.c +++ b/drivers/media/platform/xilinx/xilinx-vipp.c @@ -22,7 +22,7 @@ #include <media/v4l2-async.h> #include <media/v4l2-common.h> #include <media/v4l2-device.h> -#include <media/v4l2-of.h> +#include <media/v4l2-fwnode.h> #include "xilinx-dma.h" #include "xilinx-vipp.h" @@ -74,7 +74,7 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev, struct media_pad *local_pad; struct media_pad *remote_pad; struct xvip_graph_entity *ent; - struct v4l2_of_link link; + struct v4l2_fwnode_link link; struct device_node *ep = NULL; struct device_node *next; int ret = 0; @@ -92,7 +92,7 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev, dev_dbg(xdev->dev, "processing endpoint %s\n", ep->full_name); - ret = v4l2_of_parse_link(ep, &link); + ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link); if (ret < 0) { dev_err(xdev->dev, "failed to parse link for %s\n", ep->full_name); @@ -103,9 +103,10 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev, * the link. */ if (link.local_port >= local->num_pads) { - dev_err(xdev->dev, "invalid port number %u on %s\n", - link.local_port, link.local_node->full_name); - v4l2_of_put_link(&link); + dev_err(xdev->dev, "invalid port number %u for %s\n", + link.local_port, + to_of_node(link.local_node)->full_name); + v4l2_fwnode_put_link(&link); ret = -EINVAL; break; } @@ -114,25 +115,28 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev, if (local_pad->flags & MEDIA_PAD_FL_SINK) { dev_dbg(xdev->dev, "skipping sink port %s:%u\n", - link.local_node->full_name, link.local_port); - v4l2_of_put_link(&link); + to_of_node(link.local_node)->full_name, + link.local_port); + v4l2_fwnode_put_link(&link); continue; } /* Skip DMA engines, they will be processed separately. */ - if (link.remote_node == xdev->dev->of_node) { + if (link.remote_node == of_fwnode_handle(xdev->dev->of_node)) { dev_dbg(xdev->dev, "skipping DMA port %s:%u\n", - link.local_node->full_name, link.local_port); - v4l2_of_put_link(&link); + to_of_node(link.local_node)->full_name, + link.local_port); + v4l2_fwnode_put_link(&link); continue; } /* Find the remote entity. */ - ent = xvip_graph_find_entity(xdev, link.remote_node); + ent = xvip_graph_find_entity(xdev, + to_of_node(link.remote_node)); if (ent == NULL) { dev_err(xdev->dev, "no entity found for %s\n", - link.remote_node->full_name); - v4l2_of_put_link(&link); + to_of_node(link.remote_node)->full_name); + v4l2_fwnode_put_link(&link); ret = -ENODEV; break; } @@ -141,15 +145,16 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev, if (link.remote_port >= remote->num_pads) { dev_err(xdev->dev, "invalid port number %u on %s\n", - link.remote_port, link.remote_node->full_name); - v4l2_of_put_link(&link); + link.remote_port, + to_of_node(link.remote_node)->full_name); + v4l2_fwnode_put_link(&link); ret = -EINVAL; break; } remote_pad = &remote->pads[link.remote_port]; - v4l2_of_put_link(&link); + v4l2_fwnode_put_link(&link); /* Create the media link. */ dev_dbg(xdev->dev, "creating %s:%u -> %s:%u link\n", @@ -194,7 +199,7 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev) struct media_pad *source_pad; struct media_pad *sink_pad; struct xvip_graph_entity *ent; - struct v4l2_of_link link; + struct v4l2_fwnode_link link; struct device_node *ep = NULL; struct device_node *next; struct xvip_dma *dma; @@ -213,7 +218,7 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev) dev_dbg(xdev->dev, "processing endpoint %s\n", ep->full_name); - ret = v4l2_of_parse_link(ep, &link); + ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link); if (ret < 0) { dev_err(xdev->dev, "failed to parse link for %s\n", ep->full_name); @@ -225,7 +230,7 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev) if (dma == NULL) { dev_err(xdev->dev, "no DMA engine found for port %u\n", link.local_port); - v4l2_of_put_link(&link); + v4l2_fwnode_put_link(&link); ret = -EINVAL; break; } @@ -234,19 +239,21 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev) dma->video.name); /* Find the remote entity. */ - ent = xvip_graph_find_entity(xdev, link.remote_node); + ent = xvip_graph_find_entity(xdev, + to_of_node(link.remote_node)); if (ent == NULL) { dev_err(xdev->dev, "no entity found for %s\n", - link.remote_node->full_name); - v4l2_of_put_link(&link); + to_of_node(link.remote_node)->full_name); + v4l2_fwnode_put_link(&link); ret = -ENODEV; break; } if (link.remote_port >= ent->entity->num_pads) { dev_err(xdev->dev, "invalid port number %u on %s\n", - link.remote_port, link.remote_node->full_name); - v4l2_of_put_link(&link); + link.remote_port, + to_of_node(link.remote_node)->full_name); + v4l2_fwnode_put_link(&link); ret = -EINVAL; break; } @@ -263,7 +270,7 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev) sink_pad = &dma->pad; } - v4l2_of_put_link(&link); + v4l2_fwnode_put_link(&link); /* Create the media link. */ dev_dbg(xdev->dev, "creating %s:%u -> %s:%u link\n", @@ -383,8 +390,8 @@ static int xvip_graph_parse_one(struct xvip_composite_device *xdev, } entity->node = remote; - entity->asd.match_type = V4L2_ASYNC_MATCH_OF; - entity->asd.match.of.node = remote; + entity->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; + entity->asd.match.fwnode.fwnode = of_fwnode_handle(remote); list_add_tail(&entity->list, &xdev->entities); xdev->num_subdevs++; } diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index e422f3d56f76..5e83b76495f7 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -169,11 +169,11 @@ config IR_HIX5HD2 tristate "Hisilicon hix5hd2 IR remote control" depends on RC_CORE help - Say Y here if you want to use hisilicon hix5hd2 remote control. - To compile this driver as a module, choose M here: the module will be - called ir-hix5hd2. + Say Y here if you want to use hisilicon hix5hd2 remote control. + To compile this driver as a module, choose M here: the module will be + called ir-hix5hd2. - If you're not sure, select N here + If you're not sure, select N here config IR_IMON tristate "SoundGraph iMON Receiver and Display" diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c index 9cf3e69de16a..a4c6ad4f67c1 100644 --- a/drivers/media/rc/ati_remote.c +++ b/drivers/media/rc/ati_remote.c @@ -904,9 +904,6 @@ static int ati_remote_probe(struct usb_interface *interface, if (err) goto exit_kill_urbs; - /* use our delay for rc_dev */ - ati_remote->rdev->input_dev->rep[REP_DELAY] = repeat_delay; - /* Set up and register mouse input device */ if (mouse) { input_dev = input_allocate_device(); diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c index ccf24fd7ec1b..8711a7ff55cc 100644 --- a/drivers/media/rc/iguanair.c +++ b/drivers/media/rc/iguanair.c @@ -113,6 +113,7 @@ static void process_ir_data(struct iguanair *ir, unsigned len) break; case CMD_TX_OVERFLOW: ir->tx_overflow = true; + /* fall through */ case CMD_RECEIVER_OFF: case CMD_RECEIVER_ON: case CMD_SEND: diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index 431d33b36fb0..8d1439622533 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -702,10 +702,6 @@ static void img_ir_set_protocol(struct img_ir_priv *priv, u64 proto) { struct rc_dev *rdev = priv->hw.rdev; - spin_lock_irq(&rdev->rc_map.lock); - rdev->rc_map.rc_type = __ffs64(proto); - spin_unlock_irq(&rdev->rc_map.lock); - mutex_lock(&rdev->lock); rdev->enabled_protocols = proto; rdev->allowed_wakeup_protocols = proto; diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 3489010601b5..bd76534a2749 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -1722,7 +1722,7 @@ static void imon_incoming_scancode(struct imon_context *ictx, if (kc == KEY_KEYBOARD && !ictx->release_code) { ictx->last_keycode = kc; if (!nomouse) { - ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1; + ictx->pad_mouse = !ictx->pad_mouse; dev_dbg(dev, "toggling to %s mode\n", ictx->pad_mouse ? "mouse" : "keyboard"); spin_unlock_irqrestore(&ictx->kc_lock, flags); diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index de85f1d7ce43..a30af91710fe 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -327,16 +327,6 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, return ret; } -static int ir_lirc_open(void *data) -{ - return 0; -} - -static void ir_lirc_close(void *data) -{ - return; -} - static const struct file_operations lirc_fops = { .owner = THIS_MODULE, .write = ir_lirc_transmit_ir, @@ -354,7 +344,6 @@ static const struct file_operations lirc_fops = { static int ir_lirc_register(struct rc_dev *dev) { struct lirc_driver *drv; - struct lirc_buffer *rbuf; int rc = -ENOMEM; unsigned long features = 0; @@ -362,19 +351,12 @@ static int ir_lirc_register(struct rc_dev *dev) if (!drv) return rc; - rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL); - if (!rbuf) - goto rbuf_alloc_failed; - - rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE); - if (rc) - goto rbuf_init_failed; - if (dev->driver_type != RC_DRIVER_IR_RAW_TX) { features |= LIRC_CAN_REC_MODE2; if (dev->rx_resolution) features |= LIRC_CAN_GET_REC_RESOLUTION; } + if (dev->tx_ir) { features |= LIRC_CAN_SEND_PULSE; if (dev->s_tx_mask) @@ -403,10 +385,10 @@ static int ir_lirc_register(struct rc_dev *dev) drv->minor = -1; drv->features = features; drv->data = &dev->raw->lirc; - drv->rbuf = rbuf; - drv->set_use_inc = &ir_lirc_open; - drv->set_use_dec = &ir_lirc_close; + drv->rbuf = NULL; drv->code_length = sizeof(struct ir_raw_event) * 8; + drv->chunk_size = sizeof(int); + drv->buffer_size = LIRCBUF_SIZE; drv->fops = &lirc_fops; drv->dev = &dev->dev; drv->rdev = dev; @@ -415,19 +397,15 @@ static int ir_lirc_register(struct rc_dev *dev) drv->minor = lirc_register_driver(drv); if (drv->minor < 0) { rc = -ENODEV; - goto lirc_register_failed; + goto out; } dev->raw->lirc.drv = drv; dev->raw->lirc.dev = dev; return 0; -lirc_register_failed: -rbuf_init_failed: - kfree(rbuf); -rbuf_alloc_failed: +out: kfree(drv); - return rc; } @@ -436,9 +414,8 @@ static int ir_lirc_unregister(struct rc_dev *dev) struct lirc_codec *lirc = &dev->raw->lirc; lirc_unregister_driver(lirc->drv->minor); - lirc_buffer_free(lirc->drv->rbuf); - kfree(lirc->drv->rbuf); kfree(lirc->drv); + lirc->drv = NULL; return 0; } diff --git a/drivers/media/rc/ir-spi.c b/drivers/media/rc/ir-spi.c index c8863f36686a..4ca43383a8e8 100644 --- a/drivers/media/rc/ir-spi.c +++ b/drivers/media/rc/ir-spi.c @@ -58,7 +58,7 @@ static int ir_spi_tx(struct rc_dev *dev, /* convert the pulse/space signal to raw binary signal */ for (i = 0; i < count; i++) { int j; - u16 val = ((i + 1) % 2) ? idata->pulse : idata->space; + u16 val; if (len + buffer[i] >= IR_SPI_MAX_BUFSIZE) return -EINVAL; diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 8d60c9f00df9..db1e7b70c998 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -18,18 +18,10 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/module.h> -#include <linux/kernel.h> #include <linux/sched/signal.h> -#include <linux/errno.h> #include <linux/ioctl.h> -#include <linux/fs.h> #include <linux/poll.h> -#include <linux/completion.h> #include <linux/mutex.h> -#include <linux/wait.h> -#include <linux/unistd.h> -#include <linux/kthread.h> -#include <linux/bitops.h> #include <linux/device.h> #include <linux/cdev.h> @@ -37,9 +29,6 @@ #include <media/lirc.h> #include <media/lirc_dev.h> -static bool debug; - -#define IRCTL_DEV_NAME "BaseRemoteCtl" #define NOPLUG -1 #define LOGHEAD "lirc_dev (%s[%d]): " @@ -52,13 +41,11 @@ struct irctl { struct mutex irctl_lock; struct lirc_buffer *buf; + bool buf_internal; unsigned int chunk_size; struct device dev; struct cdev cdev; - - struct task_struct *task; - long jiffies_to_wait; }; static DEFINE_MUTEX(lirc_dev_lock); @@ -68,22 +55,11 @@ static struct irctl *irctls[MAX_IRCTL_DEVICES]; /* Only used for sysfs but defined to void otherwise */ static struct class *lirc_class; -/* helper function - * initializes the irctl structure - */ -static void lirc_irctl_init(struct irctl *ir) -{ - mutex_init(&ir->irctl_lock); - ir->d.minor = NOPLUG; -} - static void lirc_release(struct device *ld) { struct irctl *ir = container_of(ld, struct irctl, dev); - put_device(ir->dev.parent); - - if (ir->buf != ir->d.rbuf) { + if (ir->buf_internal) { lirc_buffer_free(ir->buf); kfree(ir->buf); } @@ -94,93 +70,6 @@ static void lirc_release(struct device *ld) kfree(ir); } -/* helper function - * reads key codes from driver and puts them into buffer - * returns 0 on success - */ -static int lirc_add_to_buf(struct irctl *ir) -{ - int res; - int got_data = -1; - - if (!ir->d.add_to_buf) - return 0; - - /* - * service the device as long as it is returning - * data and we have space - */ - do { - got_data++; - res = ir->d.add_to_buf(ir->d.data, ir->buf); - } while (!res); - - if (res == -ENODEV) - kthread_stop(ir->task); - - return got_data ? 0 : res; -} - -/* main function of the polling thread - */ -static int lirc_thread(void *irctl) -{ - struct irctl *ir = irctl; - - do { - if (ir->open) { - if (ir->jiffies_to_wait) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(ir->jiffies_to_wait); - } - if (kthread_should_stop()) - break; - if (!lirc_add_to_buf(ir)) - wake_up_interruptible(&ir->buf->wait_poll); - } else { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - } - } while (!kthread_should_stop()); - - return 0; -} - - -static const struct file_operations lirc_dev_fops = { - .owner = THIS_MODULE, - .read = lirc_dev_fop_read, - .write = lirc_dev_fop_write, - .poll = lirc_dev_fop_poll, - .unlocked_ioctl = lirc_dev_fop_ioctl, - .open = lirc_dev_fop_open, - .release = lirc_dev_fop_close, - .llseek = noop_llseek, -}; - -static int lirc_cdev_add(struct irctl *ir) -{ - struct lirc_driver *d = &ir->d; - struct cdev *cdev; - int retval; - - cdev = &ir->cdev; - - if (d->fops) { - cdev_init(cdev, d->fops); - cdev->owner = d->owner; - } else { - cdev_init(cdev, &lirc_dev_fops); - cdev->owner = THIS_MODULE; - } - retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor); - if (retval) - return retval; - - cdev->kobj.parent = &ir->dev.kobj; - return cdev_add(cdev, ir->dev.devt, 1); -} - static int lirc_allocate_buffer(struct irctl *ir) { int err = 0; @@ -189,8 +78,6 @@ static int lirc_allocate_buffer(struct irctl *ir) unsigned int buffer_size; struct lirc_driver *d = &ir->d; - mutex_lock(&lirc_dev_lock); - bytes_in_key = BITS_TO_LONGS(d->code_length) + (d->code_length % 8 ? 1 : 0); buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key; @@ -198,6 +85,7 @@ static int lirc_allocate_buffer(struct irctl *ir) if (d->rbuf) { ir->buf = d->rbuf; + ir->buf_internal = false; } else { ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); if (!ir->buf) { @@ -208,18 +96,20 @@ static int lirc_allocate_buffer(struct irctl *ir) err = lirc_buffer_init(ir->buf, chunk_size, buffer_size); if (err) { kfree(ir->buf); + ir->buf = NULL; goto out; } + + ir->buf_internal = true; + d->rbuf = ir->buf; } ir->chunk_size = ir->buf->chunk_size; out: - mutex_unlock(&lirc_dev_lock); - return err; } -static int lirc_allocate_driver(struct lirc_driver *d) +int lirc_register_driver(struct lirc_driver *d) { struct irctl *ir; int minor; @@ -235,6 +125,11 @@ static int lirc_allocate_driver(struct lirc_driver *d) return -EINVAL; } + if (!d->fops) { + pr_err("fops pointer not filled in!\n"); + return -EINVAL; + } + if (d->minor >= MAX_IRCTL_DEVICES) { dev_err(d->dev, "minor must be between 0 and %d!\n", MAX_IRCTL_DEVICES - 1); @@ -247,18 +142,8 @@ static int lirc_allocate_driver(struct lirc_driver *d) return -EBADRQC; } - if (d->sample_rate) { - if (2 > d->sample_rate || HZ < d->sample_rate) { - dev_err(d->dev, "invalid %d sample rate\n", - d->sample_rate); - return -EBADRQC; - } - if (!d->add_to_buf) { - dev_err(d->dev, "add_to_buf not set\n"); - return -EBADRQC; - } - } else if (!d->rbuf && !(d->fops && d->fops->read && - d->fops->poll && d->fops->unlocked_ioctl)) { + if (!d->rbuf && !(d->fops && d->fops->read && + d->fops->poll && d->fops->unlocked_ioctl)) { dev_err(d->dev, "undefined read, poll, ioctl\n"); return -EBADRQC; } @@ -288,7 +173,8 @@ static int lirc_allocate_driver(struct lirc_driver *d) err = -ENOMEM; goto out_lock; } - lirc_irctl_init(ir); + + mutex_init(&ir->irctl_lock); irctls[minor] = ir; d->minor = minor; @@ -300,32 +186,29 @@ static int lirc_allocate_driver(struct lirc_driver *d) ir->d = *d; + if (LIRC_CAN_REC(d->features)) { + err = lirc_allocate_buffer(irctls[minor]); + if (err) { + kfree(ir); + goto out_lock; + } + d->rbuf = ir->buf; + } + + device_initialize(&ir->dev); ir->dev.devt = MKDEV(MAJOR(lirc_base_dev), ir->d.minor); ir->dev.class = lirc_class; ir->dev.parent = d->dev; ir->dev.release = lirc_release; dev_set_name(&ir->dev, "lirc%d", ir->d.minor); - device_initialize(&ir->dev); - if (d->sample_rate) { - ir->jiffies_to_wait = HZ / d->sample_rate; + cdev_init(&ir->cdev, d->fops); + ir->cdev.owner = ir->d.owner; + ir->cdev.kobj.parent = &ir->dev.kobj; - /* try to fire up polling thread */ - ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev"); - if (IS_ERR(ir->task)) { - dev_err(d->dev, "cannot run thread for minor = %d\n", - d->minor); - err = -ECHILD; - goto out_sysfs; - } - } else { - /* it means - wait for external event in task queue */ - ir->jiffies_to_wait = 0; - } - - err = lirc_cdev_add(ir); + err = cdev_add(&ir->cdev, ir->dev.devt, 1); if (err) - goto out_sysfs; + goto out_free_dev; ir->attached = 1; @@ -335,37 +218,20 @@ static int lirc_allocate_driver(struct lirc_driver *d) mutex_unlock(&lirc_dev_lock); - get_device(ir->dev.parent); - dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n", ir->d.name, ir->d.minor); + return minor; + out_cdev: cdev_del(&ir->cdev); -out_sysfs: +out_free_dev: put_device(&ir->dev); out_lock: mutex_unlock(&lirc_dev_lock); return err; } - -int lirc_register_driver(struct lirc_driver *d) -{ - int minor, err = 0; - - minor = lirc_allocate_driver(d); - if (minor < 0) - return minor; - - if (LIRC_CAN_REC(d->features)) { - err = lirc_allocate_buffer(irctls[minor]); - if (err) - lirc_unregister_driver(minor); - } - - return err ? err : minor; -} EXPORT_SYMBOL(lirc_register_driver); int lirc_unregister_driver(int minor) @@ -393,10 +259,6 @@ int lirc_unregister_driver(int minor) return -ENOENT; } - /* end up polling thread */ - if (ir->task) - kthread_stop(ir->task); - dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n", ir->d.name, ir->d.minor); @@ -407,12 +269,6 @@ int lirc_unregister_driver(int minor) wake_up_interruptible(&ir->buf->wait_poll); } - mutex_lock(&ir->irctl_lock); - - if (ir->d.set_use_dec) - ir->d.set_use_dec(ir->d.data); - - mutex_unlock(&ir->irctl_lock); mutex_unlock(&lirc_dev_lock); device_del(&ir->dev); @@ -462,17 +318,10 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) goto error; } + if (ir->buf) + lirc_buffer_clear(ir->buf); + ir->open++; - if (ir->d.set_use_inc) - retval = ir->d.set_use_inc(ir->d.data); - if (retval) { - ir->open--; - } else { - if (ir->buf) - lirc_buffer_clear(ir->buf); - if (ir->task) - wake_up_process(ir->task); - } error: nonseekable_open(inode, file); @@ -497,8 +346,6 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file) rc_close(ir->d.rdev); ir->open--; - if (ir->d.set_use_dec) - ir->d.set_use_dec(ir->d.data); if (!ret) mutex_unlock(&lirc_dev_lock); @@ -517,7 +364,7 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) } if (!ir->attached) - return POLLERR; + return POLLHUP | POLLERR; if (ir->buf) { poll_wait(file, &ir->buf->wait_poll, wait); @@ -729,24 +576,6 @@ void *lirc_get_pdata(struct file *file) EXPORT_SYMBOL(lirc_get_pdata); -ssize_t lirc_dev_fop_write(struct file *file, const char __user *buffer, - size_t length, loff_t *ppos) -{ - struct irctl *ir = irctls[iminor(file_inode(file))]; - - if (!ir) { - pr_err("called with invalid irctl\n"); - return -ENODEV; - } - - if (!ir->attached) - return -ENODEV; - - return -EINVAL; -} -EXPORT_SYMBOL(lirc_dev_fop_write); - - static int __init lirc_dev_init(void) { int retval; @@ -758,7 +587,7 @@ static int __init lirc_dev_init(void) } retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES, - IRCTL_DEV_NAME); + "BaseRemoteCtl"); if (retval) { class_destroy(lirc_class); pr_err("alloc_chrdev_region failed\n"); @@ -784,6 +613,3 @@ module_exit(lirc_dev_exit); MODULE_DESCRIPTION("LIRC base driver module"); MODULE_AUTHOR("Artur Lipowski"); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 93b16fe3ab38..4530237cbb67 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -36,18 +36,18 @@ #include <linux/device.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/workqueue.h> #include <linux/usb.h> #include <linux/usb/input.h> #include <linux/pm_wakeup.h> #include <media/rc-core.h> -#define DRIVER_VERSION "1.92" +#define DRIVER_VERSION "1.93" #define DRIVER_AUTHOR "Jarod Wilson <jarod@redhat.com>" #define DRIVER_DESC "Windows Media Center Ed. eHome Infrared Transceiver " \ "device driver" #define DRIVER_NAME "mceusb" -#define USB_BUFLEN 32 /* USB reception buffer length */ #define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */ #define MCE_G1_INIT_MSGS 40 /* Init messages on gen1 hw to throw out */ @@ -417,7 +417,9 @@ struct mceusb_dev { /* usb */ struct usb_device *usbdev; struct urb *urb_in; + unsigned int pipe_in; struct usb_endpoint_descriptor *usb_ep_out; + unsigned int pipe_out; /* buffers and dma */ unsigned char *buf_in; @@ -454,6 +456,16 @@ struct mceusb_dev { u8 num_rxports; /* number of receive sensors */ u8 txports_cabled; /* bitmask of transmitters with cable */ u8 rxports_active; /* bitmask of active receive sensors */ + + /* + * support for async error handler mceusb_deferred_kevent() + * where usb_clear_halt(), usb_reset_configuration(), + * usb_reset_device(), etc. must be done in process context + */ + struct work_struct kevent; + unsigned long kevent_flags; +# define EVENT_TX_HALT 0 +# define EVENT_RX_HALT 1 }; /* MCE Device Command Strings, generally a port and command pair */ @@ -527,7 +539,7 @@ static int mceusb_cmd_datasize(u8 cmd, u8 subcmd) } static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, - int offset, int len, bool out) + int buf_len, int offset, int len, bool out) { #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) char *inout; @@ -544,7 +556,8 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, return; dev_dbg(dev, "%cx data: %*ph (length=%d)", - (out ? 't' : 'r'), min(len, USB_BUFLEN), buf, len); + (out ? 't' : 'r'), + min(len, buf_len - offset), buf + offset, len); inout = out ? "Request" : "Got"; @@ -686,6 +699,21 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, #endif } +/* + * Schedule work that can't be done in interrupt handlers + * (mceusb_dev_recv() and mce_async_callback()) nor tasklets. + * Invokes mceusb_deferred_kevent() for recovering from + * error events specified by the kevent bit field. + */ +static void mceusb_defer_kevent(struct mceusb_dev *ir, int kevent) +{ + set_bit(kevent, &ir->kevent_flags); + if (!schedule_work(&ir->kevent)) + dev_err(ir->dev, "kevent %d may have been dropped", kevent); + else + dev_dbg(ir->dev, "kevent %d scheduled", kevent); +} + static void mce_async_callback(struct urb *urb) { struct mceusb_dev *ir; @@ -701,7 +729,8 @@ static void mce_async_callback(struct urb *urb) case 0: len = urb->actual_length; - mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true); + mceusb_dev_printdata(ir, urb->transfer_buffer, len, + 0, len, true); break; case -ECONNRESET: @@ -711,6 +740,11 @@ static void mce_async_callback(struct urb *urb) break; case -EPIPE: + dev_err(ir->dev, "Error: request urb status = %d (TX HALT)", + urb->status); + mceusb_defer_kevent(ir, EVENT_TX_HALT); + break; + default: dev_err(ir->dev, "Error: request urb status = %d", urb->status); break; @@ -721,18 +755,18 @@ static void mce_async_callback(struct urb *urb) usb_free_urb(urb); } -/* request incoming or send outgoing usb packet - used to initialize remote */ +/* request outgoing (send) usb packet - used to initialize remote */ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data, int size) { - int res, pipe; + int res; struct urb *async_urb; struct device *dev = ir->dev; unsigned char *async_buf; async_urb = usb_alloc_urb(0, GFP_KERNEL); if (unlikely(!async_urb)) { - dev_err(dev, "Error, couldn't allocate urb!\n"); + dev_err(dev, "Error, couldn't allocate urb!"); return; } @@ -743,32 +777,27 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data, } /* outbound data */ - if (usb_endpoint_xfer_int(ir->usb_ep_out)) { - pipe = usb_sndintpipe(ir->usbdev, - ir->usb_ep_out->bEndpointAddress); - usb_fill_int_urb(async_urb, ir->usbdev, pipe, async_buf, - size, mce_async_callback, ir, + if (usb_endpoint_xfer_int(ir->usb_ep_out)) + usb_fill_int_urb(async_urb, ir->usbdev, ir->pipe_out, + async_buf, size, mce_async_callback, ir, ir->usb_ep_out->bInterval); - } else { - pipe = usb_sndbulkpipe(ir->usbdev, - ir->usb_ep_out->bEndpointAddress); - usb_fill_bulk_urb(async_urb, ir->usbdev, pipe, - async_buf, size, mce_async_callback, - ir); - } + else + usb_fill_bulk_urb(async_urb, ir->usbdev, ir->pipe_out, + async_buf, size, mce_async_callback, ir); + memcpy(async_buf, data, size); - dev_dbg(dev, "receive request called (size=%#x)", size); + dev_dbg(dev, "send request called (size=%#x)", size); async_urb->transfer_buffer_length = size; async_urb->dev = ir->usbdev; res = usb_submit_urb(async_urb, GFP_ATOMIC); if (res) { - dev_err(dev, "receive request FAILED! (res=%d)", res); + dev_err(dev, "send request FAILED! (res=%d)", res); return; } - dev_dbg(dev, "receive request complete (res=%d)", res); + dev_dbg(dev, "send request complete (res=%d)", res); } static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) @@ -974,7 +1003,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) switch (ir->parser_state) { case SUBCMD: ir->rem = mceusb_cmd_datasize(ir->cmd, ir->buf_in[i]); - mceusb_dev_printdata(ir, ir->buf_in, i - 1, + mceusb_dev_printdata(ir, ir->buf_in, buf_len, i - 1, ir->rem + 2, false); mceusb_handle_command(ir, i); ir->parser_state = CMD_DATA; @@ -986,7 +1015,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK) * US_TO_NS(MCE_TIME_UNIT); - dev_dbg(ir->dev, "Storing %s with duration %d", + dev_dbg(ir->dev, "Storing %s with duration %u", rawir.pulse ? "pulse" : "space", rawir.duration); @@ -1007,7 +1036,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) continue; } ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK); - mceusb_dev_printdata(ir, ir->buf_in, + mceusb_dev_printdata(ir, ir->buf_in, buf_len, i, ir->rem + 1, false); if (ir->rem) ir->parser_state = PARSE_IRDATA; @@ -1052,6 +1081,11 @@ static void mceusb_dev_recv(struct urb *urb) return; case -EPIPE: + dev_err(ir->dev, "Error: urb status = %d (RX HALT)", + urb->status); + mceusb_defer_kevent(ir, EVENT_RX_HALT); + return; + default: dev_err(ir->dev, "Error: urb status = %d", urb->status); break; @@ -1170,6 +1204,45 @@ static void mceusb_flash_led(struct mceusb_dev *ir) mce_async_out(ir, FLASH_LED, sizeof(FLASH_LED)); } +/* + * Workqueue function + * for resetting or recovering device after occurrence of error events + * specified in ir->kevent bit field. + * Function runs (via schedule_work()) in non-interrupt context, for + * calls here (such as usb_clear_halt()) requiring non-interrupt context. + */ +static void mceusb_deferred_kevent(struct work_struct *work) +{ + struct mceusb_dev *ir = + container_of(work, struct mceusb_dev, kevent); + int status; + + if (test_bit(EVENT_RX_HALT, &ir->kevent_flags)) { + usb_unlink_urb(ir->urb_in); + status = usb_clear_halt(ir->usbdev, ir->pipe_in); + if (status < 0) { + dev_err(ir->dev, "rx clear halt error %d", + status); + } + clear_bit(EVENT_RX_HALT, &ir->kevent_flags); + if (status == 0) { + status = usb_submit_urb(ir->urb_in, GFP_KERNEL); + if (status < 0) { + dev_err(ir->dev, + "rx unhalt submit urb error %d", + status); + } + } + } + + if (test_bit(EVENT_TX_HALT, &ir->kevent_flags)) { + status = usb_clear_halt(ir->usbdev, ir->pipe_out); + if (status < 0) + dev_err(ir->dev, "tx clear halt error %d", status); + clear_bit(EVENT_TX_HALT, &ir->kevent_flags); + } +} + static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir) { struct usb_device *udev = ir->usbdev; @@ -1303,6 +1376,7 @@ static int mceusb_dev_probe(struct usb_interface *intf, if (!ir) goto mem_alloc_fail; + ir->pipe_in = pipe; ir->buf_in = usb_alloc_coherent(dev, maxp, GFP_ATOMIC, &ir->dma_in); if (!ir->buf_in) goto buf_in_alloc_fail; @@ -1321,6 +1395,12 @@ static int mceusb_dev_probe(struct usb_interface *intf, /* Saving usb interface data for use by the transmitter routine */ ir->usb_ep_out = ep_out; + if (usb_endpoint_xfer_int(ep_out)) + ir->pipe_out = usb_sndintpipe(ir->usbdev, + ep_out->bEndpointAddress); + else + ir->pipe_out = usb_sndbulkpipe(ir->usbdev, + ep_out->bEndpointAddress); if (dev->descriptor.iManufacturer && usb_string(dev, dev->descriptor.iManufacturer, @@ -1332,21 +1412,32 @@ static int mceusb_dev_probe(struct usb_interface *intf, snprintf(name + strlen(name), sizeof(name) - strlen(name), " %s", buf); + /* + * Initialize async USB error handler before registering + * or activating any mceusb RX and TX functions + */ + INIT_WORK(&ir->kevent, mceusb_deferred_kevent); + ir->rc = mceusb_init_rc_dev(ir); if (!ir->rc) goto rc_dev_fail; /* wire up inbound data handler */ - usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp, - mceusb_dev_recv, ir, ep_in->bInterval); + if (usb_endpoint_xfer_int(ep_in)) + usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp, + mceusb_dev_recv, ir, ep_in->bInterval); + else + usb_fill_bulk_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp, + mceusb_dev_recv, ir); + ir->urb_in->transfer_dma = ir->dma_in; ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* flush buffers on the device */ - dev_dbg(&intf->dev, "Flushing receive buffers\n"); + dev_dbg(&intf->dev, "Flushing receive buffers"); res = usb_submit_urb(ir->urb_in, GFP_KERNEL); if (res) - dev_err(&intf->dev, "failed to flush buffers: %d\n", res); + dev_err(&intf->dev, "failed to flush buffers: %d", res); /* figure out which firmware/emulator version this hardware has */ mceusb_get_emulator_version(ir); @@ -1380,6 +1471,7 @@ static int mceusb_dev_probe(struct usb_interface *intf, /* Error-handling path */ rc_dev_fail: + cancel_work_sync(&ir->kevent); usb_put_dev(ir->usbdev); usb_kill_urb(ir->urb_in); usb_free_urb(ir->urb_in); @@ -1405,6 +1497,7 @@ static void mceusb_dev_disconnect(struct usb_interface *intf) return; ir->usbdev = NULL; + cancel_work_sync(&ir->kevent); rc_unregister_device(ir->rc); usb_kill_urb(ir->urb_in); usb_free_urb(ir->urb_in); diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c index 5576dbd6b1a4..65566d569cb1 100644 --- a/drivers/media/rc/meson-ir.c +++ b/drivers/media/rc/meson-ir.c @@ -19,6 +19,7 @@ #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/spinlock.h> +#include <linux/bitfield.h> #include <media/rc-core.h> @@ -36,7 +37,7 @@ /* only available on Meson 8b and newer */ #define IR_DEC_REG2 0x20 -#define REG0_RATE_MASK (BIT(11) - 1) +#define REG0_RATE_MASK GENMASK(11, 0) #define DECODE_MODE_NEC 0x0 #define DECODE_MODE_RAW 0x2 @@ -49,14 +50,13 @@ #define REG2_MODE_MASK GENMASK(3, 0) #define REG2_MODE_SHIFT 0 -#define REG1_TIME_IV_SHIFT 16 -#define REG1_TIME_IV_MASK ((BIT(13) - 1) << REG1_TIME_IV_SHIFT) +#define REG1_TIME_IV_MASK GENMASK(28, 16) -#define REG1_IRQSEL_MASK (BIT(2) | BIT(3)) -#define REG1_IRQSEL_NEC_MODE (0 << 2) -#define REG1_IRQSEL_RISE_FALL (1 << 2) -#define REG1_IRQSEL_FALL (2 << 2) -#define REG1_IRQSEL_RISE (3 << 2) +#define REG1_IRQSEL_MASK GENMASK(3, 2) +#define REG1_IRQSEL_NEC_MODE 0 +#define REG1_IRQSEL_RISE_FALL 1 +#define REG1_IRQSEL_FALL 2 +#define REG1_IRQSEL_RISE 3 #define REG1_RESET BIT(0) #define REG1_ENABLE BIT(15) @@ -68,7 +68,6 @@ struct meson_ir { void __iomem *reg; struct rc_dev *rc; - int irq; spinlock_t lock; }; @@ -86,18 +85,19 @@ static void meson_ir_set_mask(struct meson_ir *ir, unsigned int reg, static irqreturn_t meson_ir_irq(int irqno, void *dev_id) { struct meson_ir *ir = dev_id; - u32 duration; + u32 duration, status; DEFINE_IR_RAW_EVENT(rawir); spin_lock(&ir->lock); - duration = readl(ir->reg + IR_DEC_REG1); - duration = (duration & REG1_TIME_IV_MASK) >> REG1_TIME_IV_SHIFT; + duration = readl_relaxed(ir->reg + IR_DEC_REG1); + duration = FIELD_GET(REG1_TIME_IV_MASK, duration); rawir.duration = US_TO_NS(duration * MESON_TRATE); - rawir.pulse = !!(readl(ir->reg + IR_DEC_STATUS) & STATUS_IR_DEC_IN); + status = readl_relaxed(ir->reg + IR_DEC_STATUS); + rawir.pulse = !!(status & STATUS_IR_DEC_IN); - ir_raw_event_store_with_filter(ir->rc, &rawir); + ir_raw_event_store(ir->rc, &rawir); ir_raw_event_handle(ir->rc); spin_unlock(&ir->lock); @@ -112,7 +112,7 @@ static int meson_ir_probe(struct platform_device *pdev) struct resource *res; const char *map_name; struct meson_ir *ir; - int ret; + int irq, ret; ir = devm_kzalloc(dev, sizeof(struct meson_ir), GFP_KERNEL); if (!ir) @@ -125,13 +125,13 @@ static int meson_ir_probe(struct platform_device *pdev) return PTR_ERR(ir->reg); } - ir->irq = platform_get_irq(pdev, 0); - if (ir->irq < 0) { + irq = platform_get_irq(pdev, 0); + if (irq < 0) { dev_err(dev, "no irq resource\n"); - return ir->irq; + return irq; } - ir->rc = rc_allocate_device(RC_DRIVER_IR_RAW); + ir->rc = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW); if (!ir->rc) { dev_err(dev, "failed to allocate rc device\n"); return -ENOMEM; @@ -143,7 +143,6 @@ static int meson_ir_probe(struct platform_device *pdev) ir->rc->input_id.bustype = BUS_HOST; map_name = of_get_property(node, "linux,rc-map-name", NULL); ir->rc->map_name = map_name ? map_name : RC_MAP_EMPTY; - ir->rc->dev.parent = dev; ir->rc->allowed_protocols = RC_BIT_ALL_IR_DECODER; ir->rc->rx_resolution = US_TO_NS(MESON_TRATE); ir->rc->timeout = MS_TO_NS(200); @@ -152,16 +151,16 @@ static int meson_ir_probe(struct platform_device *pdev) spin_lock_init(&ir->lock); platform_set_drvdata(pdev, ir); - ret = rc_register_device(ir->rc); + ret = devm_rc_register_device(dev, ir->rc); if (ret) { dev_err(dev, "failed to register rc device\n"); - goto out_free; + return ret; } - ret = devm_request_irq(dev, ir->irq, meson_ir_irq, 0, "ir-meson", ir); + ret = devm_request_irq(dev, irq, meson_ir_irq, 0, NULL, ir); if (ret) { dev_err(dev, "failed to request irq\n"); - goto out_unreg; + return ret; } /* Reset the decoder */ @@ -171,29 +170,22 @@ static int meson_ir_probe(struct platform_device *pdev) /* Set general operation mode (= raw/software decoding) */ if (of_device_is_compatible(node, "amlogic,meson6-ir")) meson_ir_set_mask(ir, IR_DEC_REG1, REG1_MODE_MASK, - DECODE_MODE_RAW << REG1_MODE_SHIFT); + FIELD_PREP(REG1_MODE_MASK, DECODE_MODE_RAW)); else meson_ir_set_mask(ir, IR_DEC_REG2, REG2_MODE_MASK, - DECODE_MODE_RAW << REG2_MODE_SHIFT); + FIELD_PREP(REG2_MODE_MASK, DECODE_MODE_RAW)); /* Set rate */ meson_ir_set_mask(ir, IR_DEC_REG0, REG0_RATE_MASK, MESON_TRATE - 1); /* IRQ on rising and falling edges */ meson_ir_set_mask(ir, IR_DEC_REG1, REG1_IRQSEL_MASK, - REG1_IRQSEL_RISE_FALL); + FIELD_PREP(REG1_IRQSEL_MASK, REG1_IRQSEL_RISE_FALL)); /* Enable the decoder */ meson_ir_set_mask(ir, IR_DEC_REG1, REG1_ENABLE, REG1_ENABLE); dev_info(dev, "receiver initialized\n"); return 0; -out_unreg: - rc_unregister_device(ir->rc); - ir->rc = NULL; -out_free: - rc_free_device(ir->rc); - - return ret; } static int meson_ir_remove(struct platform_device *pdev) @@ -206,11 +198,35 @@ static int meson_ir_remove(struct platform_device *pdev) meson_ir_set_mask(ir, IR_DEC_REG1, REG1_ENABLE, 0); spin_unlock_irqrestore(&ir->lock, flags); - rc_unregister_device(ir->rc); - return 0; } +static void meson_ir_shutdown(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + struct meson_ir *ir = platform_get_drvdata(pdev); + unsigned long flags; + + spin_lock_irqsave(&ir->lock, flags); + + /* + * Set operation mode to NEC/hardware decoding to give + * bootloader a chance to power the system back on + */ + if (of_device_is_compatible(node, "amlogic,meson6-ir")) + meson_ir_set_mask(ir, IR_DEC_REG1, REG1_MODE_MASK, + DECODE_MODE_NEC << REG1_MODE_SHIFT); + else + meson_ir_set_mask(ir, IR_DEC_REG2, REG2_MODE_MASK, + DECODE_MODE_NEC << REG2_MODE_SHIFT); + + /* Set rate to default value */ + meson_ir_set_mask(ir, IR_DEC_REG0, REG0_RATE_MASK, 0x13); + + spin_unlock_irqrestore(&ir->lock, flags); +} + static const struct of_device_id meson_ir_match[] = { { .compatible = "amlogic,meson6-ir" }, { .compatible = "amlogic,meson8b-ir" }, @@ -222,6 +238,7 @@ MODULE_DEVICE_TABLE(of, meson_ir_match); static struct platform_driver meson_ir_driver = { .probe = meson_ir_probe, .remove = meson_ir_remove, + .shutdown = meson_ir_shutdown, .driver = { .name = DRIVER_NAME, .of_match_table = meson_ir_match, diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 6ec73357fa47..802e559cc30e 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -1703,6 +1703,16 @@ static int rc_setup_rx_device(struct rc_dev *dev) if (dev->close) dev->input_dev->close = ir_close; + dev->input_dev->dev.parent = &dev->dev; + memcpy(&dev->input_dev->id, &dev->input_id, sizeof(dev->input_id)); + dev->input_dev->phys = dev->input_phys; + dev->input_dev->name = dev->input_name; + + /* rc_open will be called here */ + rc = input_register_device(dev->input_dev); + if (rc) + goto out_table; + /* * Default delay of 250ms is too short for some protocols, especially * since the timeout is currently set to 250ms. Increase it to 500ms, @@ -1718,16 +1728,6 @@ static int rc_setup_rx_device(struct rc_dev *dev) */ dev->input_dev->rep[REP_PERIOD] = 125; - dev->input_dev->dev.parent = &dev->dev; - memcpy(&dev->input_dev->id, &dev->input_id, sizeof(dev->input_id)); - dev->input_dev->phys = dev->input_phys; - dev->input_dev->name = dev->input_name; - - /* rc_open will be called here */ - rc = input_register_device(dev->input_dev); - if (rc) - goto out_table; - return 0; out_table: diff --git a/drivers/media/rc/sir_ir.c b/drivers/media/rc/sir_ir.c index e12ec50bf0bf..5ee3a2301c05 100644 --- a/drivers/media/rc/sir_ir.c +++ b/drivers/media/rc/sir_ir.c @@ -53,16 +53,13 @@ static DEFINE_SPINLOCK(hardware_lock); /* Communication with user-space */ static void add_read_queue(int flag, unsigned long val); -static int init_chrdev(void); /* Hardware */ static irqreturn_t sir_interrupt(int irq, void *dev_id); static void send_space(unsigned long len); static void send_pulse(unsigned long len); -static int init_hardware(void); +static void init_hardware(void); static void drop_hardware(void); /* Initialisation */ -static int init_port(void); -static void drop_port(void); static inline unsigned int sinp(int offset) { @@ -122,28 +119,6 @@ static void add_read_queue(int flag, unsigned long val) ir_raw_event_store_with_filter(rcdev, &ev); } -static int init_chrdev(void) -{ - rcdev = devm_rc_allocate_device(&sir_ir_dev->dev, RC_DRIVER_IR_RAW); - if (!rcdev) - return -ENOMEM; - - rcdev->input_name = "SIR IrDA port"; - rcdev->input_phys = KBUILD_MODNAME "/input0"; - rcdev->input_id.bustype = BUS_HOST; - rcdev->input_id.vendor = 0x0001; - rcdev->input_id.product = 0x0001; - rcdev->input_id.version = 0x0100; - rcdev->tx_ir = sir_tx_ir; - rcdev->allowed_protocols = RC_BIT_ALL_IR_DECODER; - rcdev->driver_name = KBUILD_MODNAME; - rcdev->map_name = RC_MAP_RC6_MCE; - rcdev->timeout = IR_DEFAULT_TIMEOUT; - rcdev->dev.parent = &sir_ir_dev->dev; - - return devm_rc_register_device(&sir_ir_dev->dev, rcdev); -} - /* SECTION: Hardware */ static void sir_timeout(unsigned long data) { @@ -183,9 +158,15 @@ static irqreturn_t sir_interrupt(int irq, void *dev_id) static unsigned long delt; unsigned long deltintr; unsigned long flags; + int counter = 0; int iir, lsr; while ((iir = inb(io + UART_IIR) & UART_IIR_ID)) { + if (++counter > 256) { + dev_err(&sir_ir_dev->dev, "Trapped in interrupt"); + break; + } + switch (iir & UART_IIR_ID) { /* FIXME toto treba preriedit */ case UART_IIR_MSI: (void)inb(io + UART_MSR); @@ -282,7 +263,7 @@ static void send_pulse(unsigned long len) } } -static int init_hardware(void) +static void init_hardware(void) { unsigned long flags; @@ -304,7 +285,6 @@ static int init_hardware(void) /* turn on UART */ outb(UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2, io + UART_MCR); spin_unlock_irqrestore(&hardware_lock, flags); - return 0; } static void drop_hardware(void) @@ -320,61 +300,55 @@ static void drop_hardware(void) } /* SECTION: Initialisation */ - -static int init_port(void) +static int sir_ir_probe(struct platform_device *dev) { int retval; + rcdev = devm_rc_allocate_device(&sir_ir_dev->dev, RC_DRIVER_IR_RAW); + if (!rcdev) + return -ENOMEM; + + rcdev->input_name = "SIR IrDA port"; + rcdev->input_phys = KBUILD_MODNAME "/input0"; + rcdev->input_id.bustype = BUS_HOST; + rcdev->input_id.vendor = 0x0001; + rcdev->input_id.product = 0x0001; + rcdev->input_id.version = 0x0100; + rcdev->tx_ir = sir_tx_ir; + rcdev->allowed_protocols = RC_BIT_ALL_IR_DECODER; + rcdev->driver_name = KBUILD_MODNAME; + rcdev->map_name = RC_MAP_RC6_MCE; + rcdev->timeout = IR_DEFAULT_TIMEOUT; + rcdev->dev.parent = &sir_ir_dev->dev; + setup_timer(&timerlist, sir_timeout, 0); /* get I/O port access and IRQ line */ - if (!request_region(io, 8, KBUILD_MODNAME)) { + if (!devm_request_region(&sir_ir_dev->dev, io, 8, KBUILD_MODNAME)) { pr_err("i/o port 0x%.4x already in use.\n", io); return -EBUSY; } - retval = request_irq(irq, sir_interrupt, 0, - KBUILD_MODNAME, NULL); + retval = devm_request_irq(&sir_ir_dev->dev, irq, sir_interrupt, 0, + KBUILD_MODNAME, NULL); if (retval < 0) { - release_region(io, 8); pr_err("IRQ %d already in use.\n", irq); return retval; } pr_info("I/O port 0x%.4x, IRQ %d.\n", io, irq); - return 0; -} - -static void drop_port(void) -{ - free_irq(irq, NULL); - del_timer_sync(&timerlist); - release_region(io, 8); -} - -static int init_sir_ir(void) -{ - int retval; - - retval = init_port(); + retval = devm_rc_register_device(&sir_ir_dev->dev, rcdev); if (retval < 0) return retval; - init_hardware(); - return 0; -} - -static int sir_ir_probe(struct platform_device *dev) -{ - int retval; - retval = init_chrdev(); - if (retval < 0) - return retval; + init_hardware(); - return init_sir_ir(); + return 0; } static int sir_ir_remove(struct platform_device *dev) { + drop_hardware(); + del_timer_sync(&timerlist); return 0; } @@ -415,8 +389,6 @@ pdev_alloc_fail: static void __exit sir_ir_exit(void) { - drop_hardware(); - drop_port(); platform_device_unregister(sir_ir_dev); platform_driver_unregister(&sir_ir_driver); } diff --git a/drivers/media/tuners/tda18271-fe.c b/drivers/media/tuners/tda18271-fe.c index b4e5fa2ff5e5..147155553648 100644 --- a/drivers/media/tuners/tda18271-fe.c +++ b/drivers/media/tuners/tda18271-fe.c @@ -960,7 +960,7 @@ static int tda18271_set_params(struct dvb_frontend *fe) break; case SYS_DVBC_ANNEX_B: bw = 6000000; - /* falltrough */ + /* fall through */ case SYS_DVBC_ANNEX_A: case SYS_DVBC_ANNEX_C: if (bw <= 6000000) { diff --git a/drivers/media/tuners/xc5000.c b/drivers/media/tuners/xc5000.c index e823aafce276..0e7e4fdf9e50 100644 --- a/drivers/media/tuners/xc5000.c +++ b/drivers/media/tuners/xc5000.c @@ -565,38 +565,16 @@ static int xc_get_totalgain(struct xc5000_priv *priv, u16 *totalgain) return xc5000_readreg(priv, XREG_TOTALGAIN, totalgain); } -static u16 wait_for_lock(struct xc5000_priv *priv) -{ - u16 lock_state = 0; - int watch_dog_count = 40; - - while ((lock_state == 0) && (watch_dog_count > 0)) { - xc_get_lock_status(priv, &lock_state); - if (lock_state != 1) { - msleep(5); - watch_dog_count--; - } - } - return lock_state; -} - #define XC_TUNE_ANALOG 0 #define XC_TUNE_DIGITAL 1 static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode) { - int found = 0; - dprintk(1, "%s(%u)\n", __func__, freq_hz); if (xc_set_rf_frequency(priv, freq_hz) != 0) - return 0; - - if (mode == XC_TUNE_ANALOG) { - if (wait_for_lock(priv) == 1) - found = 1; - } + return -EREMOTEIO; - return found; + return 0; } static int xc_set_xtal(struct dvb_frontend *fe) @@ -788,6 +766,7 @@ static int xc5000_set_digital_params(struct dvb_frontend *fe) if (!bw) bw = 6000000; /* fall to OFDM handling */ + /* fall through */ case SYS_DMBTH: case SYS_DVBT: case SYS_DVBT2: diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c index 7e0c9b795e52..34dc7e062471 100644 --- a/drivers/media/usb/au0828/au0828-dvb.c +++ b/drivers/media/usb/au0828/au0828-dvb.c @@ -105,6 +105,15 @@ static struct tda18271_config hauppauge_woodbury_tunerconfig = { static void au0828_restart_dvb_streaming(struct work_struct *work); +static void au0828_bulk_timeout(unsigned long data) +{ + struct au0828_dev *dev = (struct au0828_dev *) data; + + dprintk(1, "%s called\n", __func__); + dev->bulk_timeout_running = 0; + schedule_work(&dev->restart_streaming); +} + /*-------------------------------------------------------------------*/ static void urb_completion(struct urb *purb) { @@ -138,6 +147,13 @@ static void urb_completion(struct urb *purb) ptr[0], purb->actual_length); schedule_work(&dev->restart_streaming); return; + } else if (dev->bulk_timeout_running == 1) { + /* The URB handler has fired, so cancel timer which would + * restart endpoint if we hadn't + */ + dprintk(1, "%s cancelling bulk timeout\n", __func__); + dev->bulk_timeout_running = 0; + del_timer(&dev->bulk_timeout); } /* Feed the transport payload into the kernel demux */ @@ -160,6 +176,11 @@ static int stop_urb_transfer(struct au0828_dev *dev) if (!dev->urb_streaming) return 0; + if (dev->bulk_timeout_running == 1) { + dev->bulk_timeout_running = 0; + del_timer(&dev->bulk_timeout); + } + dev->urb_streaming = false; for (i = 0; i < URB_COUNT; i++) { if (dev->urbs[i]) { @@ -232,6 +253,11 @@ static int start_urb_transfer(struct au0828_dev *dev) } dev->urb_streaming = true; + + /* If we don't valid data within 1 second, restart stream */ + mod_timer(&dev->bulk_timeout, jiffies + (HZ)); + dev->bulk_timeout_running = 1; + return 0; } @@ -622,6 +648,10 @@ int au0828_dvb_register(struct au0828_dev *dev) return ret; } + dev->bulk_timeout.function = au0828_bulk_timeout; + dev->bulk_timeout.data = (unsigned long) dev; + init_timer(&dev->bulk_timeout); + return 0; } diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index 88e59748ebc2..05e445fe0b77 100644 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h @@ -195,6 +195,8 @@ struct au0828_dev { /* Digital */ struct au0828_dvb dvb; struct work_struct restart_streaming; + struct timer_list bulk_timeout; + int bulk_timeout_running; #ifdef CONFIG_VIDEO_AU0828_V4L2 /* Analog */ diff --git a/drivers/media/usb/cpia2/cpia2_core.c b/drivers/media/usb/cpia2/cpia2_core.c index b1d13444ff30..0efba0da0a45 100644 --- a/drivers/media/usb/cpia2/cpia2_core.c +++ b/drivers/media/usb/cpia2/cpia2_core.c @@ -173,7 +173,8 @@ int cpia2_do_command(struct camera_data *cam, cmd.start = CPIA2_VP_DEVICEH; break; case CPIA2_CMD_SET_VP_BRIGHTNESS: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_VP_BRIGHTNESS: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -183,14 +184,16 @@ int cpia2_do_command(struct camera_data *cam, cmd.start = CPIA2_VP5_EXPOSURE_TARGET; break; case CPIA2_CMD_SET_CONTRAST: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_CONTRAST: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; cmd.start = CPIA2_VP_YRANGE; break; case CPIA2_CMD_SET_VP_SATURATION: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_VP_SATURATION: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -200,28 +203,32 @@ int cpia2_do_command(struct camera_data *cam, cmd.start = CPIA2_VP5_MCUVSATURATION; break; case CPIA2_CMD_SET_VP_GPIO_DATA: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_VP_GPIO_DATA: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; cmd.start = CPIA2_VP_GPIO_DATA; break; case CPIA2_CMD_SET_VP_GPIO_DIRECTION: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_VP_GPIO_DIRECTION: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; cmd.start = CPIA2_VP_GPIO_DIRECTION; break; case CPIA2_CMD_SET_VC_MP_GPIO_DATA: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_VC_MP_GPIO_DATA: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; cmd.reg_count = 1; cmd.start = CPIA2_VC_MP_DATA; break; case CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /*fall through */ case CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; cmd.reg_count = 1; @@ -235,7 +242,8 @@ int cpia2_do_command(struct camera_data *cam, cmd.buffer.block_data[0] = param; break; case CPIA2_CMD_SET_FLICKER_MODES: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_FLICKER_MODES: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -280,8 +288,9 @@ int cpia2_do_command(struct camera_data *cam, cmd.start = CPIA2_SYSTEM_SYSTEM_CONTROL; cmd.buffer.block_data[0] = CPIA2_SYSTEM_CONTROL_CLEAR_ERR; break; - case CPIA2_CMD_SET_USER_MODE: /* Then fall through */ + case CPIA2_CMD_SET_USER_MODE: cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_USER_MODE: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -300,14 +309,16 @@ int cpia2_do_command(struct camera_data *cam, cmd.buffer.block_data[0] = param; break; case CPIA2_CMD_SET_WAKEUP: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_WAKEUP: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; cmd.reg_count = 1; cmd.start = CPIA2_VC_WAKEUP; break; case CPIA2_CMD_SET_PW_CONTROL: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_PW_CONTROL: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; cmd.reg_count = 1; @@ -319,7 +330,8 @@ int cpia2_do_command(struct camera_data *cam, cmd.start = CPIA2_VP_SYSTEMSTATE; break; case CPIA2_CMD_SET_SYSTEM_CTRL: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_SYSTEM_CTRL: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; @@ -327,21 +339,24 @@ int cpia2_do_command(struct camera_data *cam, cmd.start = CPIA2_SYSTEM_SYSTEM_CONTROL; break; case CPIA2_CMD_SET_VP_SYSTEM_CTRL: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_VP_SYSTEM_CTRL: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; cmd.start = CPIA2_VP_SYSTEMCTRL; break; case CPIA2_CMD_SET_VP_EXP_MODES: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_VP_EXP_MODES: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; cmd.start = CPIA2_VP_EXPOSURE_MODES; break; case CPIA2_CMD_SET_DEVICE_CONFIG: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_DEVICE_CONFIG: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -361,7 +376,8 @@ int cpia2_do_command(struct camera_data *cam, cmd.start = CPIA2_SENSOR_CR1; break; case CPIA2_CMD_SET_VC_CONTROL: - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_VC_CONTROL: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; cmd.reg_count = 1; @@ -395,7 +411,8 @@ int cpia2_do_command(struct camera_data *cam, case CPIA2_CMD_SET_USER_EFFECTS: /* Note: Be careful with this as this register can also affect flicker modes */ - cmd.buffer.block_data[0] = param; /* Then fall through */ + cmd.buffer.block_data[0] = param; + /* fall through */ case CPIA2_CMD_GET_USER_EFFECTS: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; diff --git a/drivers/media/usb/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig index 58de80bff4c7..6276d9b2198b 100644 --- a/drivers/media/usb/cx231xx/Kconfig +++ b/drivers/media/usb/cx231xx/Kconfig @@ -52,6 +52,8 @@ config VIDEO_CX231XX_DVB select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT + select DVB_MN88473 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_R820T if MEDIA_SUBDRV_AUTOSELECT ---help--- This adds support for DVB cards based on the diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index a1007d005290..e0daa9b6c2a0 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -868,6 +868,33 @@ struct cx231xx_board cx231xx_boards[] = { .amux = CX231XX_AMUX_LINE_IN, } }, }, + [CX231XX_BOARD_ASTROMETA_T2HYBRID] = { + .name = "Astrometa T2hybrid", + .tuner_type = TUNER_ABSENT, + .has_dvb = 1, + .output_mode = OUT_MODE_VIP11, + .agc_analog_digital_select_gpio = 0x01, + .ctl_pin_status_mask = 0xffffffc4, + .demod_addr = 0x18, /* 0x30 >> 1 */ + .demod_i2c_master = I2C_1_MUX_1, + .gpio_pin_status_mask = 0xa, + .norm = V4L2_STD_NTSC, + .tuner_addr = 0x3a, /* 0x74 >> 1 */ + .tuner_i2c_master = I2C_1_MUX_3, + .tuner_scl_gpio = 0x1a, + .tuner_sda_gpio = 0x1b, + .tuner_sif_gpio = 0x05, + .input = {{ + .type = CX231XX_VMUX_TELEVISION, + .vmux = CX231XX_VIN_1_1, + .amux = CX231XX_AMUX_VIDEO, + }, { + .type = CX231XX_VMUX_COMPOSITE1, + .vmux = CX231XX_VIN_2_1, + .amux = CX231XX_AMUX_LINE_IN, + }, + }, + }, }; const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); @@ -937,6 +964,8 @@ struct usb_device_id cx231xx_id_table[] = { .driver_info = CX231XX_BOARD_TERRATEC_GRABBY}, {USB_DEVICE(0x1b80, 0xd3b2), .driver_info = CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD}, + {USB_DEVICE(0x15f4, 0x0135), + .driver_info = CX231XX_BOARD_ASTROMETA_T2HYBRID}, {}, }; @@ -1013,6 +1042,11 @@ void cx231xx_pre_card_setup(struct cx231xx *dev) dev_info(dev->dev, "Identified as %s (card=%d)\n", dev->board.name, dev->model); + if (CX231XX_BOARD_ASTROMETA_T2HYBRID == dev->model) { + /* turn on demodulator chip */ + cx231xx_set_gpio_value(dev, 0x03, 0x01); + } + /* set the direction for GPIO pins */ if (dev->board.tuner_gpio) { cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index 46427fd3b220..ee3eeeb600f8 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c @@ -37,6 +37,8 @@ #include "mb86a20s.h" #include "si2157.h" #include "lgdt3306a.h" +#include "r820t.h" +#include "mn88473.h" MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); @@ -164,6 +166,13 @@ static struct lgdt3306a_config hauppauge_955q_lgdt3306a_config = { .xtalMHz = 25, }; +static struct r820t_config astrometa_t2hybrid_r820t_config = { + .i2c_addr = 0x3a, /* 0x74 >> 1 */ + .xtal = 16000000, + .rafael_chip = CHIP_R828D, + .max_i2c_msg_len = 2, +}; + static inline void print_err_status(struct cx231xx *dev, int packet, int status) { char *errmsg = "Unknown"; @@ -1019,6 +1028,46 @@ static int dvb_init(struct cx231xx *dev) dev->dvb->i2c_client_tuner = client; break; } + case CX231XX_BOARD_ASTROMETA_T2HYBRID: + { + struct i2c_client *client; + struct i2c_board_info info = {}; + struct mn88473_config mn88473_config = {}; + + /* attach demodulator chip */ + mn88473_config.i2c_wr_max = 16; + mn88473_config.xtal = 25000000; + mn88473_config.fe = &dev->dvb->frontend; + + strlcpy(info.type, "mn88473", sizeof(info.type)); + info.addr = dev->board.demod_addr; + info.platform_data = &mn88473_config; + + request_module(info.type); + client = i2c_new_device(demod_i2c, &info); + + if (client == NULL || client->dev.driver == NULL) { + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_demod = client; + + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + + /* attach tuner chip */ + dvb_attach(r820t_attach, dev->dvb->frontend, + tuner_i2c, + &astrometa_t2hybrid_r820t_config); + break; + } default: dev_err(dev->dev, "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", diff --git a/drivers/media/usb/cx231xx/cx231xx-input.c b/drivers/media/usb/cx231xx/cx231xx-input.c index 6e80f3c573f3..eecf074b0a48 100644 --- a/drivers/media/usb/cx231xx/cx231xx-input.c +++ b/drivers/media/usb/cx231xx/cx231xx-input.c @@ -30,7 +30,7 @@ static int get_key_isdbt(struct IR_i2c *ir, enum rc_type *protocol, int rc; u8 cmd, scancode; - dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__); + dev_dbg(&ir->rc->dev, "%s\n", __func__); /* poll IR chip */ rc = i2c_master_recv(ir->c, &cmd, 1); @@ -48,8 +48,7 @@ static int get_key_isdbt(struct IR_i2c *ir, enum rc_type *protocol, scancode = bitrev8(cmd); - dev_dbg(&ir->rc->input_dev->dev, "cmd %02x, scan = %02x\n", - cmd, scancode); + dev_dbg(&ir->rc->dev, "cmd %02x, scan = %02x\n", cmd, scancode); *protocol = RC_TYPE_OTHER; *pscancode = scancode; diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 6414188ffdfa..f67f86876625 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -1134,7 +1134,7 @@ void cx231xx_v4l2_create_entities(struct cx231xx *dev) /* The DVB core will handle it */ if (dev->tuner_type == TUNER_ABSENT) continue; - /* fall though */ + /* fall through */ default: /* just to shut up a gcc warning */ ent->function = MEDIA_ENT_F_CONN_RF; break; diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index d9792ea4bbc6..986c64ba5b56 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -79,6 +79,7 @@ #define CX231XX_BOARD_HAUPPAUGE_955Q 21 #define CX231XX_BOARD_TERRATEC_GRABBY 22 #define CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD 23 +#define CX231XX_BOARD_ASTROMETA_T2HYBRID 24 /* Limits minimum and default number of buffers */ #define CX231XX_MIN_BUF 4 diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c index caa1e6101f58..612431ab0fb3 100644 --- a/drivers/media/usb/dvb-usb-v2/af9015.c +++ b/drivers/media/usb/dvb-usb-v2/af9015.c @@ -52,6 +52,7 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) case READ_I2C: write = 0; state->buf[2] |= 0x01; /* set I2C direction */ + /* fall through */ case WRITE_I2C: state->buf[0] = READ_WRITE_I2C; break; diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index 924adfdb660d..594360a63c18 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -1065,6 +1065,7 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) } break; } + /* fall through */ case 0x22f0: st->i2c_gate = 5; adap->fe[0] = dvb_attach(m88rs2000_attach, diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c index ffb49c28b15a..0eb33e043079 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c @@ -316,7 +316,7 @@ fail: static int mxl111sf_i2c_send_data(struct mxl111sf_state *state, u8 index, u8 *wdata) { - int ret = mxl111sf_ctrl_msg(state->d, wdata[0], + int ret = mxl111sf_ctrl_msg(state, wdata[0], &wdata[1], 25, NULL, 0); mxl_fail(ret); @@ -326,7 +326,7 @@ static int mxl111sf_i2c_send_data(struct mxl111sf_state *state, static int mxl111sf_i2c_get_data(struct mxl111sf_state *state, u8 index, u8 *wdata, u8 *rdata) { - int ret = mxl111sf_ctrl_msg(state->d, wdata[0], + int ret = mxl111sf_ctrl_msg(state, wdata[0], &wdata[1], 25, rdata, 24); mxl_fail(ret); diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index abf69d8fa469..b0d5904a4ea6 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -24,9 +24,6 @@ #include "lgdt3305.h" #include "lg2160.h" -/* Max transfer size done by I2C transfer functions */ -#define MAX_XFER_SIZE 64 - int dvb_usb_mxl111sf_debug; module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able))."); @@ -55,27 +52,34 @@ MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int)."); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -int mxl111sf_ctrl_msg(struct dvb_usb_device *d, +int mxl111sf_ctrl_msg(struct mxl111sf_state *state, u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { + struct dvb_usb_device *d = state->d; int wo = (rbuf == NULL || rlen == 0); /* write-only */ int ret; - u8 sndbuf[MAX_XFER_SIZE]; - if (1 + wlen > sizeof(sndbuf)) { + if (1 + wlen > MXL_MAX_XFER_SIZE) { pr_warn("%s: len=%d is too big!\n", __func__, wlen); return -EOPNOTSUPP; } pr_debug("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen); - memset(sndbuf, 0, 1+wlen); + mutex_lock(&state->msg_lock); + memset(state->sndbuf, 0, 1+wlen); + memset(state->rcvbuf, 0, rlen); + + state->sndbuf[0] = cmd; + memcpy(&state->sndbuf[1], wbuf, wlen); - sndbuf[0] = cmd; - memcpy(&sndbuf[1], wbuf, wlen); + ret = (wo) ? dvb_usbv2_generic_write(d, state->sndbuf, 1+wlen) : + dvb_usbv2_generic_rw(d, state->sndbuf, 1+wlen, state->rcvbuf, + rlen); + + memcpy(rbuf, state->rcvbuf, rlen); + mutex_unlock(&state->msg_lock); - ret = (wo) ? dvb_usbv2_generic_write(d, sndbuf, 1+wlen) : - dvb_usbv2_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen); mxl_fail(ret); return ret; @@ -91,7 +95,7 @@ int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data) u8 buf[2]; int ret; - ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2); + ret = mxl111sf_ctrl_msg(state, MXL_CMD_REG_READ, &addr, 1, buf, 2); if (mxl_fail(ret)) { mxl_debug("error reading reg: 0x%02x", addr); goto fail; @@ -117,7 +121,7 @@ int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data) pr_debug("W: (0x%02x, 0x%02x)\n", addr, data); - ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0); + ret = mxl111sf_ctrl_msg(state, MXL_CMD_REG_WRITE, buf, 2, NULL, 0); if (mxl_fail(ret)) pr_err("error writing reg: 0x%02x, val: 0x%02x", addr, data); return ret; @@ -926,6 +930,8 @@ static int mxl111sf_init(struct dvb_usb_device *d) .len = sizeof(eeprom), .buf = eeprom }, }; + mutex_init(&state->msg_lock); + ret = get_chip_info(state); if (mxl_fail(ret)) pr_err("failed to get chip info during probe"); diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.h b/drivers/media/usb/dvb-usb-v2/mxl111sf.h index 846260e0eec0..3e6f5880bd1e 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h @@ -19,6 +19,9 @@ #include <media/tveeprom.h> #include <media/media-entity.h> +/* Max transfer size done by I2C transfer functions */ +#define MXL_MAX_XFER_SIZE 64 + #define MXL_EP1_REG_READ 1 #define MXL_EP2_REG_WRITE 2 #define MXL_EP3_INTERRUPT 3 @@ -86,6 +89,9 @@ struct mxl111sf_state { struct mutex fe_lock; u8 num_frontends; struct mxl111sf_adap_state adap_state[3]; + u8 sndbuf[MXL_MAX_XFER_SIZE]; + u8 rcvbuf[MXL_MAX_XFER_SIZE]; + struct mutex msg_lock; #ifdef CONFIG_MEDIA_CONTROLLER_DVB struct media_entity tuner; struct media_pad tuner_pads[2]; @@ -108,7 +114,7 @@ int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state, /* needed for hardware i2c functions in mxl111sf-i2c.c: * mxl111sf_i2c_send_data / mxl111sf_i2c_get_data */ -int mxl111sf_ctrl_msg(struct dvb_usb_device *d, +int mxl111sf_ctrl_msg(struct mxl111sf_state *state, u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen); #define mxl_printk(kern, fmt, arg...) \ diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index 85ab3fa48f9a..6a57fc6d3472 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c @@ -1659,6 +1659,7 @@ static int dib8096_set_param_override(struct dvb_frontend *fe) switch (band) { default: deb_info("Warning : Rf frequency (%iHz) is not in the supported range, using VHF switch ", fe->dtv_property_cache.frequency); + /* fall through */ case BAND_VHF: state->dib8000_ops.set_gpio(fe, 3, 0, 1); break; diff --git a/drivers/media/usb/dvb-usb/dvb-usb-remote.c b/drivers/media/usb/dvb-usb/dvb-usb-remote.c index 059ded59208e..f05f1fc80729 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c @@ -131,6 +131,11 @@ static void legacy_dvb_usb_read_remote_control(struct work_struct *work) case REMOTE_KEY_PRESSED: deb_rc("key pressed\n"); d->last_event = event; + input_event(d->input_dev, EV_KEY, event, 1); + input_sync(d->input_dev); + input_event(d->input_dev, EV_KEY, d->last_event, 0); + input_sync(d->input_dev); + break; case REMOTE_KEY_REPEAT: deb_rc("key repeated\n"); input_event(d->input_dev, EV_KEY, event, 1); diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 6e654e5026dd..57b187240110 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -1840,11 +1840,12 @@ static int dw2102_load_firmware(struct usb_device *dev, switch (le16_to_cpu(dev->descriptor.idProduct)) { case USB_PID_TEVII_S650: dw2104_properties.rc.core.rc_codes = RC_MAP_TEVII_NEC; + /* fall through */ case USB_PID_DW2104: reset = 1; dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, DW210X_WRITE_MSG); - /* break omitted intentionally */ + /* fall through */ case USB_PID_DW3101: reset = 0; dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, @@ -1877,6 +1878,7 @@ static int dw2102_load_firmware(struct usb_device *dev, break; } } + /* fall through */ case 0x2101: dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2, DW210X_READ_MSG); diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index a12b599a1fa2..146341aeb782 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -2855,7 +2855,7 @@ static int em28xx_hint_board(struct em28xx *dev) "Your board has no unique USB ID.\n" "A hint were successfully done, based on eeprom hash.\n" "This method is not 100%% failproof.\n" - "If the board were missdetected, please email this log to:\n" + "If the board were misdetected, please email this log to:\n" "\tV4L Mailing List <linux-media@vger.kernel.org>\n" "Board detected as %s\n", em28xx_boards[dev->model].name); @@ -2885,7 +2885,7 @@ static int em28xx_hint_board(struct em28xx *dev) "Your board has no unique USB ID.\n" "A hint were successfully done, based on i2c devicelist hash.\n" "This method is not 100%% failproof.\n" - "If the board were missdetected, please email this log to:\n" + "If the board were misdetected, please email this log to:\n" "\tV4L Mailing List <linux-media@vger.kernel.org>\n" "Board detected as %s\n", em28xx_boards[dev->model].name); diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index 19ccff41c7eb..1d0d8cc06103 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -91,22 +91,16 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, if (len > URB_MAX_CTRL_SIZE) return -EINVAL; - em28xx_regdbg("(pipe 0x%08x): IN: %02x %02x %02x %02x %02x %02x %02x %02x ", - pipe, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - req, 0, 0, - reg & 0xff, reg >> 8, - len & 0xff, len >> 8); - mutex_lock(&dev->ctrl_urb_lock); ret = usb_control_msg(udev, pipe, req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0000, reg, dev->urb_buf, len, HZ); if (ret < 0) { - em28xx_regdbg("(pipe 0x%08x): IN: %02x %02x %02x %02x %02x %02x %02x %02x failed\n", + em28xx_regdbg("(pipe 0x%08x): IN: %02x %02x %02x %02x %02x %02x %02x %02x failed with error %i\n", pipe, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, req, 0, 0, reg & 0xff, reg >> 8, - len & 0xff, len >> 8); + len & 0xff, len >> 8, ret); mutex_unlock(&dev->ctrl_urb_lock); return usb_translate_errors(ret); } @@ -116,7 +110,7 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, mutex_unlock(&dev->ctrl_urb_lock); - em28xx_regdbg("(pipe 0x%08x): IN: %02x %02x %02x %02x %02x %02x %02x %02x failed <<< %*ph\n", + em28xx_regdbg("(pipe 0x%08x): IN: %02x %02x %02x %02x %02x %02x %02x %02x <<< %*ph\n", pipe, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, req, 0, 0, reg & 0xff, reg >> 8, @@ -164,13 +158,6 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, if ((len < 1) || (len > URB_MAX_CTRL_SIZE)) return -EINVAL; - em28xx_regdbg("(pipe 0x%08x): OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>> %*ph\n", - pipe, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - req, 0, 0, - reg & 0xff, reg >> 8, - len & 0xff, len >> 8, len, buf); - mutex_lock(&dev->ctrl_urb_lock); memcpy(dev->urb_buf, buf, len); ret = usb_control_msg(udev, pipe, req, @@ -178,8 +165,22 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, 0x0000, reg, dev->urb_buf, len, HZ); mutex_unlock(&dev->ctrl_urb_lock); - if (ret < 0) + if (ret < 0) { + em28xx_regdbg("(pipe 0x%08x): OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>> %*ph failed with error %i\n", + pipe, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + req, 0, 0, + reg & 0xff, reg >> 8, + len & 0xff, len >> 8, len, buf, ret); return usb_translate_errors(ret); + } + + em28xx_regdbg("(pipe 0x%08x): OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>> %*ph\n", + pipe, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + req, 0, 0, + reg & 0xff, reg >> 8, + len & 0xff, len >> 8, len, buf); if (dev->wait_after_write) msleep(dev->wait_after_write); diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c index be5e25d1a2e8..6ad8d4849680 100644 --- a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c +++ b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c @@ -345,6 +345,11 @@ int s5k83a_start(struct sd *sd) to assume that there is no better way of accomplishing this */ sd->rotation_thread = kthread_create(rotation_thread_function, sd, "rotation thread"); + if (IS_ERR(sd->rotation_thread)) { + err = PTR_ERR(sd->rotation_thread); + sd->rotation_thread = NULL; + return err; + } wake_up_process(sd->rotation_thread); /* Preinit the sensor */ diff --git a/drivers/media/usb/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c index f4c41f043cda..cdb79c5f0c38 100644 --- a/drivers/media/usb/gspca/ov519.c +++ b/drivers/media/usb/gspca/ov519.c @@ -3526,7 +3526,8 @@ static void ov511_mode_init_regs(struct sd *sd) sd->clockdiv = 0; break; } - /* Fall through for 640x480 case */ + /* For 640x480 case */ + /* fall through */ default: /* case 20: */ /* case 15: */ diff --git a/drivers/media/usb/pwc/pwc-v4l.c b/drivers/media/usb/pwc/pwc-v4l.c index 92f04db6bbae..043b2b97cee6 100644 --- a/drivers/media/usb/pwc/pwc-v4l.c +++ b/drivers/media/usb/pwc/pwc-v4l.c @@ -568,7 +568,8 @@ static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl) pdev->gain_valid = true; if (!DEVICE_USE_CODEC3(pdev->type)) break; - /* Fall through for CODEC3 where autogain also controls expo */ + /* For CODEC3 where autogain also controls expo */ + /* fall through */ case V4L2_CID_EXPOSURE_AUTO: if (pdev->exposure_valid && time_before(jiffies, pdev->last_exposure_update + HZ / 4)) { diff --git a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c index 71bd68548c9c..ad468efc4399 100644 --- a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c +++ b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c @@ -123,11 +123,12 @@ static void rain_irq_work_handler(struct work_struct *work) char data; spin_lock_irqsave(&rain->buf_lock, flags); - exit_loop = rain->buf_len == 0; if (rain->buf_len) { data = rain->buf[rain->buf_rd_idx]; rain->buf_len--; rain->buf_rd_idx = (rain->buf_rd_idx + 1) & 0xff; + } else { + exit_loop = true; } spin_unlock_irqrestore(&rain->buf_lock, flags); @@ -296,7 +297,7 @@ static int rain_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, cec_msg_destination(msg), msg->msg[1]); for (i = 2; i < msg->len; i++) { snprintf(hex, sizeof(hex), "%02x", msg->msg[i]); - strncat(cmd, hex, sizeof(cmd)); + strlcat(cmd, hex, sizeof(cmd)); } } mutex_lock(&rain->write_lock); @@ -336,6 +337,7 @@ static int rain_connect(struct serio *serio, struct serio_driver *drv) serio_set_drvdata(serio, rain); INIT_WORK(&rain->work, rain_irq_work_handler); mutex_init(&rain->write_lock); + spin_lock_init(&rain->buf_lock); err = serio_open(serio, drv); if (err) diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index a9d4484f7626..6a88b1dbb3a0 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -1803,6 +1803,8 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) default: pr_info("s2255 unknown resp\n"); } + pdata++; + break; default: pdata++; break; diff --git a/drivers/media/usb/tm6000/tm6000-input.c b/drivers/media/usb/tm6000/tm6000-input.c index 39c15bb2b20c..1a033f57fcc1 100644 --- a/drivers/media/usb/tm6000/tm6000-input.c +++ b/drivers/media/usb/tm6000/tm6000-input.c @@ -63,7 +63,6 @@ struct tm6000_IR { u8 wait:1; u8 pwled:2; u8 submit_urb:1; - u16 key_addr; struct urb *int_urb; /* IR device properties */ @@ -321,9 +320,6 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 *rc_type) dprintk(2, "%s\n",__func__); - if ((rc->rc_map.scan) && (*rc_type == RC_BIT_NEC)) - ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff); - ir->rc_type = *rc_type; tm6000_ir_config(ir); diff --git a/drivers/media/usb/usbvision/usbvision-i2c.c b/drivers/media/usb/usbvision/usbvision-i2c.c index 5a3f788ad033..fdf6b6e285da 100644 --- a/drivers/media/usb/usbvision/usbvision-i2c.c +++ b/drivers/media/usb/usbvision/usbvision-i2c.c @@ -311,10 +311,13 @@ usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr, switch (len) { case 4: buf[3] = usbvision_read_reg(usbvision, USBVISION_SER_DAT4); + /* fall through */ case 3: buf[2] = usbvision_read_reg(usbvision, USBVISION_SER_DAT3); + /* fall through */ case 2: buf[1] = usbvision_read_reg(usbvision, USBVISION_SER_DAT2); + /* fall through */ case 1: buf[0] = usbvision_read_reg(usbvision, USBVISION_SER_DAT1); break; diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index f9c3325aa4d4..756322c4ac05 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -1427,8 +1427,8 @@ static int usbvision_probe(struct usb_interface *intf, int model, i, ret; PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u", - dev->descriptor.idVendor, - dev->descriptor.idProduct, ifnum); + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct), ifnum); model = devid->driver_info; if (model < 0 || model >= usbvision_device_data_size) { diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 46d6be0bb316..70842c5af05b 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2013,6 +2013,7 @@ static int uvc_probe(struct usb_interface *intf, { struct usb_device *udev = interface_to_usbdev(intf); struct uvc_device *dev; + int function; int ret; if (id->idVendor && id->idProduct) @@ -2044,9 +2045,27 @@ static int uvc_probe(struct usb_interface *intf, strlcpy(dev->name, udev->product, sizeof dev->name); else snprintf(dev->name, sizeof dev->name, - "UVC Camera (%04x:%04x)", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); + "UVC Camera (%04x:%04x)", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); + + /* + * Add iFunction or iInterface to names when available as additional + * distinguishers between interfaces. iFunction is prioritized over + * iInterface which matches Windows behavior at the point of writing. + */ + if (intf->intf_assoc && intf->intf_assoc->iFunction != 0) + function = intf->intf_assoc->iFunction; + else + function = intf->cur_altsetting->desc.iInterface; + if (function != 0) { + size_t len; + + strlcat(dev->name, ": ", sizeof(dev->name)); + len = strlen(dev->name); + usb_string(udev, function, dev->name + len, + sizeof(dev->name) - len); + } /* Parse the Video Class control descriptor. */ if (uvc_parse_control(dev) < 0) { @@ -2441,6 +2460,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX | UVC_QUIRK_BUILTIN_ISIGHT }, + /* Apple Built-In iSight via iBridge */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x05ac, + .idProduct = 0x8600, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_DEF }, /* Foxlink ("HP Webcam" on HP Mini 5103) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 47d93a938dde..fb86d6af398d 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -1323,11 +1323,11 @@ static void uvc_video_complete(struct urb *urb) default: uvc_printk(KERN_WARNING, "Non-zero status (%d) in video " "completion handler.\n", urb->status); - + /* fall through */ case -ENOENT: /* usb_kill_urb() called. */ if (stream->frozen) return; - + /* fall through */ case -ECONNRESET: /* usb_unlink_urb() called. */ case -ESHUTDOWN: /* The endpoint is being disabled. */ uvc_queue_cancel(queue, urb->status == -ESHUTDOWN); diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig index 6b1b78ff1417..a35c33686abf 100644 --- a/drivers/media/v4l2-core/Kconfig +++ b/drivers/media/v4l2-core/Kconfig @@ -55,6 +55,9 @@ config V4L2_FLASH_LED_CLASS When in doubt, say N. +config V4L2_FWNODE + tristate + # Used by drivers that need Videobuf modules config VIDEOBUF_GEN tristate diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile index 795a5352761d..098ad5fd5231 100644 --- a/drivers/media/v4l2-core/Makefile +++ b/drivers/media/v4l2-core/Makefile @@ -10,9 +10,7 @@ videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ ifeq ($(CONFIG_COMPAT),y) videodev-objs += v4l2-compat-ioctl32.o endif -ifeq ($(CONFIG_OF),y) - videodev-objs += v4l2-of.o -endif +obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o ifeq ($(CONFIG_TRACEPOINTS),y) videodev-objs += vb2-trace.o v4l2-trace.o endif diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 96cc733f35ef..cbd919d4edd2 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -14,6 +14,7 @@ #include <linux/list.h> #include <linux/module.h> #include <linux/mutex.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/types.h> @@ -40,10 +41,14 @@ static bool match_devname(struct v4l2_subdev *sd, return !strcmp(asd->match.device_name.name, dev_name(sd->dev)); } -static bool match_of(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) +static bool match_fwnode(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) { - return !of_node_cmp(of_node_full_name(sd->of_node), - of_node_full_name(asd->match.of.node)); + if (!is_of_node(sd->fwnode) || !is_of_node(asd->match.fwnode.fwnode)) + return sd->fwnode == asd->match.fwnode.fwnode; + + return !of_node_cmp(of_node_full_name(to_of_node(sd->fwnode)), + of_node_full_name( + to_of_node(asd->match.fwnode.fwnode))); } static bool match_custom(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) @@ -77,8 +82,8 @@ static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier * case V4L2_ASYNC_MATCH_I2C: match = match_i2c; break; - case V4L2_ASYNC_MATCH_OF: - match = match_of; + case V4L2_ASYNC_MATCH_FWNODE: + match = match_fwnode; break; default: /* Cannot happen, unless someone breaks us */ @@ -157,7 +162,7 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, case V4L2_ASYNC_MATCH_CUSTOM: case V4L2_ASYNC_MATCH_DEVNAME: case V4L2_ASYNC_MATCH_I2C: - case V4L2_ASYNC_MATCH_OF: + case V4L2_ASYNC_MATCH_FWNODE: break; default: dev_err(notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL, @@ -280,8 +285,8 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd) * (struct v4l2_subdev.dev), and async sub-device does not * exist independently of the device at any point of time. */ - if (!sd->of_node && sd->dev) - sd->of_node = sd->dev->of_node; + if (!sd->fwnode && sd->dev) + sd->fwnode = dev_fwnode(sd->dev); mutex_lock(&list_lock); diff --git a/drivers/media/v4l2-core/v4l2-flash-led-class.c b/drivers/media/v4l2-core/v4l2-flash-led-class.c index 794e563f24f8..7b8288108e8a 100644 --- a/drivers/media/v4l2-core/v4l2-flash-led-class.c +++ b/drivers/media/v4l2-core/v4l2-flash-led-class.c @@ -12,7 +12,7 @@ #include <linux/led-class-flash.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/of.h> +#include <linux/property.h> #include <linux/slab.h> #include <linux/types.h> #include <media/v4l2-flash-led-class.h> @@ -612,7 +612,7 @@ static const struct v4l2_subdev_internal_ops v4l2_flash_subdev_internal_ops = { static const struct v4l2_subdev_ops v4l2_flash_subdev_ops; struct v4l2_flash *v4l2_flash_init( - struct device *dev, struct device_node *of_node, + struct device *dev, struct fwnode_handle *fwn, struct led_classdev_flash *fled_cdev, struct led_classdev_flash *iled_cdev, const struct v4l2_flash_ops *ops, @@ -638,7 +638,7 @@ struct v4l2_flash *v4l2_flash_init( v4l2_flash->iled_cdev = iled_cdev; v4l2_flash->ops = ops; sd->dev = dev; - sd->of_node = of_node ? of_node : led_cdev->dev->of_node; + sd->fwnode = fwn ? fwn : dev_fwnode(led_cdev->dev); v4l2_subdev_init(sd, &v4l2_flash_subdev_ops); sd->internal_ops = &v4l2_flash_subdev_internal_ops; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; @@ -654,7 +654,7 @@ struct v4l2_flash *v4l2_flash_init( if (ret < 0) goto err_init_controls; - of_node_get(sd->of_node); + fwnode_handle_get(sd->fwnode); ret = v4l2_async_register_subdev(sd); if (ret < 0) @@ -663,7 +663,7 @@ struct v4l2_flash *v4l2_flash_init( return v4l2_flash; err_async_register_sd: - of_node_put(sd->of_node); + fwnode_handle_put(sd->fwnode); v4l2_ctrl_handler_free(sd->ctrl_handler); err_init_controls: media_entity_cleanup(&sd->entity); @@ -683,7 +683,7 @@ void v4l2_flash_release(struct v4l2_flash *v4l2_flash) v4l2_async_unregister_subdev(sd); - of_node_put(sd->of_node); + fwnode_handle_put(sd->fwnode); v4l2_ctrl_handler_free(sd->ctrl_handler); media_entity_cleanup(&sd->entity); diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c new file mode 100644 index 000000000000..153c53ca3925 --- /dev/null +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -0,0 +1,345 @@ +/* + * V4L2 fwnode binding parsing library + * + * The origins of the V4L2 fwnode library are in V4L2 OF library that + * formerly was located in v4l2-of.c. + * + * Copyright (c) 2016 Intel Corporation. + * Author: Sakari Ailus <sakari.ailus@linux.intel.com> + * + * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. + * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> + * + * Copyright (C) 2012 Renesas Electronics Corp. + * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + */ +#include <linux/acpi.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/property.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/types.h> + +#include <media/v4l2-fwnode.h> + +static int v4l2_fwnode_endpoint_parse_csi_bus(struct fwnode_handle *fwnode, + struct v4l2_fwnode_endpoint *vep) +{ + struct v4l2_fwnode_bus_mipi_csi2 *bus = &vep->bus.mipi_csi2; + bool have_clk_lane = false; + unsigned int flags = 0, lanes_used = 0; + unsigned int i; + u32 v; + int rval; + + rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0); + if (rval > 0) { + u32 array[ARRAY_SIZE(bus->data_lanes)]; + + bus->num_data_lanes = + min_t(int, ARRAY_SIZE(bus->data_lanes), rval); + + fwnode_property_read_u32_array(fwnode, "data-lanes", array, + bus->num_data_lanes); + + for (i = 0; i < bus->num_data_lanes; i++) { + if (lanes_used & BIT(array[i])) + pr_warn("duplicated lane %u in data-lanes\n", + array[i]); + lanes_used |= BIT(array[i]); + + bus->data_lanes[i] = array[i]; + } + } + + rval = fwnode_property_read_u32_array(fwnode, "lane-polarities", NULL, + 0); + if (rval > 0) { + u32 array[ARRAY_SIZE(bus->lane_polarities)]; + + if (rval < 1 + bus->num_data_lanes /* clock + data */) { + pr_warn("too few lane-polarities entries (need %u, got %u)\n", + 1 + bus->num_data_lanes, rval); + return -EINVAL; + } + + fwnode_property_read_u32_array(fwnode, "lane-polarities", array, + 1 + bus->num_data_lanes); + + for (i = 0; i < 1 + bus->num_data_lanes; i++) + bus->lane_polarities[i] = array[i]; + } + + if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) { + if (lanes_used & BIT(v)) + pr_warn("duplicated lane %u in clock-lanes\n", v); + lanes_used |= BIT(v); + + bus->clock_lane = v; + have_clk_lane = true; + } + + if (fwnode_property_present(fwnode, "clock-noncontinuous")) + flags |= V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK; + else if (have_clk_lane || bus->num_data_lanes > 0) + flags |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; + + bus->flags = flags; + vep->bus_type = V4L2_MBUS_CSI2; + + return 0; +} + +static void v4l2_fwnode_endpoint_parse_parallel_bus( + struct fwnode_handle *fwnode, struct v4l2_fwnode_endpoint *vep) +{ + struct v4l2_fwnode_bus_parallel *bus = &vep->bus.parallel; + unsigned int flags = 0; + u32 v; + + if (!fwnode_property_read_u32(fwnode, "hsync-active", &v)) + flags |= v ? V4L2_MBUS_HSYNC_ACTIVE_HIGH : + V4L2_MBUS_HSYNC_ACTIVE_LOW; + + if (!fwnode_property_read_u32(fwnode, "vsync-active", &v)) + flags |= v ? V4L2_MBUS_VSYNC_ACTIVE_HIGH : + V4L2_MBUS_VSYNC_ACTIVE_LOW; + + if (!fwnode_property_read_u32(fwnode, "field-even-active", &v)) + flags |= v ? V4L2_MBUS_FIELD_EVEN_HIGH : + V4L2_MBUS_FIELD_EVEN_LOW; + if (flags) + vep->bus_type = V4L2_MBUS_PARALLEL; + else + vep->bus_type = V4L2_MBUS_BT656; + + if (!fwnode_property_read_u32(fwnode, "pclk-sample", &v)) + flags |= v ? V4L2_MBUS_PCLK_SAMPLE_RISING : + V4L2_MBUS_PCLK_SAMPLE_FALLING; + + if (!fwnode_property_read_u32(fwnode, "data-active", &v)) + flags |= v ? V4L2_MBUS_DATA_ACTIVE_HIGH : + V4L2_MBUS_DATA_ACTIVE_LOW; + + if (fwnode_property_present(fwnode, "slave-mode")) + flags |= V4L2_MBUS_SLAVE; + else + flags |= V4L2_MBUS_MASTER; + + if (!fwnode_property_read_u32(fwnode, "bus-width", &v)) + bus->bus_width = v; + + if (!fwnode_property_read_u32(fwnode, "data-shift", &v)) + bus->data_shift = v; + + if (!fwnode_property_read_u32(fwnode, "sync-on-green-active", &v)) + flags |= v ? V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH : + V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW; + + bus->flags = flags; + +} + +/** + * v4l2_fwnode_endpoint_parse() - parse all fwnode node properties + * @fwnode: pointer to the endpoint's fwnode handle + * @vep: pointer to the V4L2 fwnode data structure + * + * All properties are optional. If none are found, we don't set any flags. This + * means the port has a static configuration and no properties have to be + * specified explicitly. If any properties that identify the bus as parallel + * are found and slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if + * we recognise the bus as serial CSI-2 and clock-noncontinuous isn't set, we + * set the V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. The caller should hold a + * reference to @fwnode. + * + * NOTE: This function does not parse properties the size of which is variable + * without a low fixed limit. Please use v4l2_fwnode_endpoint_alloc_parse() in + * new drivers instead. + * + * Return: 0 on success or a negative error code on failure. + */ +int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode, + struct v4l2_fwnode_endpoint *vep) +{ + int rval; + + fwnode_graph_parse_endpoint(fwnode, &vep->base); + + /* Zero fields from bus_type to until the end */ + memset(&vep->bus_type, 0, sizeof(*vep) - + offsetof(typeof(*vep), bus_type)); + + rval = v4l2_fwnode_endpoint_parse_csi_bus(fwnode, vep); + if (rval) + return rval; + /* + * Parse the parallel video bus properties only if none + * of the MIPI CSI-2 specific properties were found. + */ + if (vep->bus.mipi_csi2.flags == 0) + v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep); + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_parse); + +/* + * v4l2_fwnode_endpoint_free() - free the V4L2 fwnode acquired by + * v4l2_fwnode_endpoint_alloc_parse() + * @vep - the V4L2 fwnode the resources of which are to be released + * + * It is safe to call this function with NULL argument or on a V4L2 fwnode the + * parsing of which failed. + */ +void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep) +{ + if (IS_ERR_OR_NULL(vep)) + return; + + kfree(vep->link_frequencies); + kfree(vep); +} +EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_free); + +/** + * v4l2_fwnode_endpoint_alloc_parse() - parse all fwnode node properties + * @fwnode: pointer to the endpoint's fwnode handle + * + * All properties are optional. If none are found, we don't set any flags. This + * means the port has a static configuration and no properties have to be + * specified explicitly. If any properties that identify the bus as parallel + * are found and slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if + * we recognise the bus as serial CSI-2 and clock-noncontinuous isn't set, we + * set the V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. The caller should hold a + * reference to @fwnode. + * + * v4l2_fwnode_endpoint_alloc_parse() has two important differences to + * v4l2_fwnode_endpoint_parse(): + * + * 1. It also parses variable size data. + * + * 2. The memory it has allocated to store the variable size data must be freed + * using v4l2_fwnode_endpoint_free() when no longer needed. + * + * Return: Pointer to v4l2_fwnode_endpoint if successful, on an error pointer + * on error. + */ +struct v4l2_fwnode_endpoint *v4l2_fwnode_endpoint_alloc_parse( + struct fwnode_handle *fwnode) +{ + struct v4l2_fwnode_endpoint *vep; + int rval; + + vep = kzalloc(sizeof(*vep), GFP_KERNEL); + if (!vep) + return ERR_PTR(-ENOMEM); + + rval = v4l2_fwnode_endpoint_parse(fwnode, vep); + if (rval < 0) + goto out_err; + + rval = fwnode_property_read_u64_array(fwnode, "link-frequencies", + NULL, 0); + if (rval < 0) + goto out_err; + + vep->link_frequencies = + kmalloc_array(rval, sizeof(*vep->link_frequencies), GFP_KERNEL); + if (!vep->link_frequencies) { + rval = -ENOMEM; + goto out_err; + } + + vep->nr_of_link_frequencies = rval; + + rval = fwnode_property_read_u64_array(fwnode, "link-frequencies", + vep->link_frequencies, + vep->nr_of_link_frequencies); + if (rval < 0) + goto out_err; + + return vep; + +out_err: + v4l2_fwnode_endpoint_free(vep); + return ERR_PTR(rval); +} +EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_alloc_parse); + +/** + * v4l2_fwnode_endpoint_parse_link() - parse a link between two endpoints + * @__fwnode: pointer to the endpoint's fwnode at the local end of the link + * @link: pointer to the V4L2 fwnode link data structure + * + * Fill the link structure with the local and remote nodes and port numbers. + * The local_node and remote_node fields are set to point to the local and + * remote port's parent nodes respectively (the port parent node being the + * parent node of the port node if that node isn't a 'ports' node, or the + * grand-parent node of the port node otherwise). + * + * A reference is taken to both the local and remote nodes, the caller must use + * v4l2_fwnode_endpoint_put_link() to drop the references when done with the + * link. + * + * Return: 0 on success, or -ENOLINK if the remote endpoint fwnode can't be + * found. + */ +int v4l2_fwnode_parse_link(struct fwnode_handle *__fwnode, + struct v4l2_fwnode_link *link) +{ + const char *port_prop = is_of_node(__fwnode) ? "reg" : "port"; + struct fwnode_handle *fwnode; + + memset(link, 0, sizeof(*link)); + + fwnode = fwnode_get_parent(__fwnode); + fwnode_property_read_u32(fwnode, port_prop, &link->local_port); + fwnode = fwnode_get_next_parent(fwnode); + if (is_of_node(fwnode) && + of_node_cmp(to_of_node(fwnode)->name, "ports") == 0) + fwnode = fwnode_get_next_parent(fwnode); + link->local_node = fwnode; + + fwnode = fwnode_graph_get_remote_endpoint(__fwnode); + if (!fwnode) { + fwnode_handle_put(fwnode); + return -ENOLINK; + } + + fwnode = fwnode_get_parent(fwnode); + fwnode_property_read_u32(fwnode, port_prop, &link->remote_port); + fwnode = fwnode_get_next_parent(fwnode); + if (is_of_node(fwnode) && + of_node_cmp(to_of_node(fwnode)->name, "ports") == 0) + fwnode = fwnode_get_next_parent(fwnode); + link->remote_node = fwnode; + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_fwnode_parse_link); + +/** + * v4l2_fwnode_put_link() - drop references to nodes in a link + * @link: pointer to the V4L2 fwnode link data structure + * + * Drop references to the local and remote nodes in the link. This function + * must be called on every link parsed with v4l2_fwnode_parse_link(). + */ +void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link) +{ + fwnode_handle_put(link->local_node); + fwnode_handle_put(link->remote_node); +} +EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>"); +MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); +MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index e5a2187381db..4f27cfa134a1 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2472,20 +2472,22 @@ struct v4l2_ioctl_info { }; /* This control needs a priority check */ -#define INFO_FL_PRIO (1 << 0) +#define INFO_FL_PRIO (1 << 0) /* This control can be valid if the filehandle passes a control handler. */ -#define INFO_FL_CTRL (1 << 1) +#define INFO_FL_CTRL (1 << 1) /* This is a standard ioctl, no need for special code */ -#define INFO_FL_STD (1 << 2) +#define INFO_FL_STD (1 << 2) /* This is ioctl has its own function */ -#define INFO_FL_FUNC (1 << 3) +#define INFO_FL_FUNC (1 << 3) /* Queuing ioctl */ -#define INFO_FL_QUEUE (1 << 4) +#define INFO_FL_QUEUE (1 << 4) +/* Always copy back result, even on error */ +#define INFO_FL_ALWAYS_COPY (1 << 5) /* Zero struct from after the field to the end */ #define INFO_FL_CLEAR(v4l2_struct, field) \ ((offsetof(struct v4l2_struct, field) + \ sizeof(((struct v4l2_struct *)0)->field)) << 16) -#define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16) +#define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16) #define IOCTL_INFO_STD(_ioctl, _vidioc, _debug, _flags) \ [_IOC_NR(_ioctl)] = { \ @@ -2536,8 +2538,8 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)), IOCTL_INFO_STD(VIDIOC_G_INPUT, vidioc_g_input, v4l_print_u32, 0), IOCTL_INFO_FNC(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO), - IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, 0), - IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, INFO_FL_ALWAYS_COPY), + IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO | INFO_FL_ALWAYS_COPY), IOCTL_INFO_STD(VIDIOC_G_OUTPUT, vidioc_g_output, v4l_print_u32, 0), IOCTL_INFO_FNC(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)), @@ -2583,7 +2585,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_CREATE_BUFS, v4l_create_bufs, v4l_print_create_buffers, INFO_FL_PRIO | INFO_FL_QUEUE), IOCTL_INFO_FNC(VIDIOC_PREPARE_BUF, v4l_prepare_buf, v4l_print_buffer, INFO_FL_QUEUE), IOCTL_INFO_STD(VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings, v4l_print_enum_dv_timings, INFO_FL_CLEAR(v4l2_enum_dv_timings, pad)), - IOCTL_INFO_STD(VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings, v4l_print_dv_timings, 0), + IOCTL_INFO_STD(VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings, v4l_print_dv_timings, INFO_FL_ALWAYS_COPY), IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, INFO_FL_CLEAR(v4l2_dv_timings_cap, type)), IOCTL_INFO_FNC(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0), IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)), @@ -2801,6 +2803,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, void *parg = (void *)arg; long err = -EINVAL; bool has_array_args; + bool always_copy = false; size_t array_size = 0; void __user *user_ptr = NULL; void **kernel_ptr = NULL; @@ -2830,8 +2833,10 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, */ if (v4l2_is_known_ioctl(cmd)) { u32 flags = v4l2_ioctls[_IOC_NR(cmd)].flags; + if (flags & INFO_FL_CLEAR_MASK) n = (flags & INFO_FL_CLEAR_MASK) >> 16; + always_copy = flags & INFO_FL_ALWAYS_COPY; } if (copy_from_user(parg, (void __user *)arg, n)) @@ -2885,9 +2890,11 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, err = -EFAULT; goto out_array_args; } - /* VIDIOC_QUERY_DV_TIMINGS can return an error, but still have valid - results that must be returned. */ - if (err < 0 && cmd != VIDIOC_QUERY_DV_TIMINGS) + /* + * Some ioctls can return an error, but still have valid + * results that must be returned. + */ + if (err < 0 && !always_copy) goto out; out_array_args: diff --git a/drivers/media/v4l2-core/v4l2-of.c b/drivers/media/v4l2-core/v4l2-of.c deleted file mode 100644 index 4f59f442dd0a..000000000000 --- a/drivers/media/v4l2-core/v4l2-of.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * V4L2 OF binding parsing library - * - * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. - * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> - * - * Copyright (C) 2012 Renesas Electronics Corp. - * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/types.h> - -#include <media/v4l2-of.h> - -static int v4l2_of_parse_csi_bus(const struct device_node *node, - struct v4l2_of_endpoint *endpoint) -{ - struct v4l2_of_bus_mipi_csi2 *bus = &endpoint->bus.mipi_csi2; - struct property *prop; - bool have_clk_lane = false; - unsigned int flags = 0, lanes_used = 0; - u32 v; - - prop = of_find_property(node, "data-lanes", NULL); - if (prop) { - const __be32 *lane = NULL; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(bus->data_lanes); i++) { - lane = of_prop_next_u32(prop, lane, &v); - if (!lane) - break; - - if (lanes_used & BIT(v)) - pr_warn("%s: duplicated lane %u in data-lanes\n", - node->full_name, v); - lanes_used |= BIT(v); - - bus->data_lanes[i] = v; - } - bus->num_data_lanes = i; - } - - prop = of_find_property(node, "lane-polarities", NULL); - if (prop) { - const __be32 *polarity = NULL; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(bus->lane_polarities); i++) { - polarity = of_prop_next_u32(prop, polarity, &v); - if (!polarity) - break; - bus->lane_polarities[i] = v; - } - - if (i < 1 + bus->num_data_lanes /* clock + data */) { - pr_warn("%s: too few lane-polarities entries (need %u, got %u)\n", - node->full_name, 1 + bus->num_data_lanes, i); - return -EINVAL; - } - } - - if (!of_property_read_u32(node, "clock-lanes", &v)) { - if (lanes_used & BIT(v)) - pr_warn("%s: duplicated lane %u in clock-lanes\n", - node->full_name, v); - lanes_used |= BIT(v); - - bus->clock_lane = v; - have_clk_lane = true; - } - - if (of_get_property(node, "clock-noncontinuous", &v)) - flags |= V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK; - else if (have_clk_lane || bus->num_data_lanes > 0) - flags |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; - - bus->flags = flags; - endpoint->bus_type = V4L2_MBUS_CSI2; - - return 0; -} - -static void v4l2_of_parse_parallel_bus(const struct device_node *node, - struct v4l2_of_endpoint *endpoint) -{ - struct v4l2_of_bus_parallel *bus = &endpoint->bus.parallel; - unsigned int flags = 0; - u32 v; - - if (!of_property_read_u32(node, "hsync-active", &v)) - flags |= v ? V4L2_MBUS_HSYNC_ACTIVE_HIGH : - V4L2_MBUS_HSYNC_ACTIVE_LOW; - - if (!of_property_read_u32(node, "vsync-active", &v)) - flags |= v ? V4L2_MBUS_VSYNC_ACTIVE_HIGH : - V4L2_MBUS_VSYNC_ACTIVE_LOW; - - if (!of_property_read_u32(node, "field-even-active", &v)) - flags |= v ? V4L2_MBUS_FIELD_EVEN_HIGH : - V4L2_MBUS_FIELD_EVEN_LOW; - if (flags) - endpoint->bus_type = V4L2_MBUS_PARALLEL; - else - endpoint->bus_type = V4L2_MBUS_BT656; - - if (!of_property_read_u32(node, "pclk-sample", &v)) - flags |= v ? V4L2_MBUS_PCLK_SAMPLE_RISING : - V4L2_MBUS_PCLK_SAMPLE_FALLING; - - if (!of_property_read_u32(node, "data-active", &v)) - flags |= v ? V4L2_MBUS_DATA_ACTIVE_HIGH : - V4L2_MBUS_DATA_ACTIVE_LOW; - - if (of_get_property(node, "slave-mode", &v)) - flags |= V4L2_MBUS_SLAVE; - else - flags |= V4L2_MBUS_MASTER; - - if (!of_property_read_u32(node, "bus-width", &v)) - bus->bus_width = v; - - if (!of_property_read_u32(node, "data-shift", &v)) - bus->data_shift = v; - - if (!of_property_read_u32(node, "sync-on-green-active", &v)) - flags |= v ? V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH : - V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW; - - bus->flags = flags; - -} - -/** - * v4l2_of_parse_endpoint() - parse all endpoint node properties - * @node: pointer to endpoint device_node - * @endpoint: pointer to the V4L2 OF endpoint data structure - * - * All properties are optional. If none are found, we don't set any flags. - * This means the port has a static configuration and no properties have - * to be specified explicitly. - * If any properties that identify the bus as parallel are found and - * slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if we recognise - * the bus as serial CSI-2 and clock-noncontinuous isn't set, we set the - * V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. - * The caller should hold a reference to @node. - * - * NOTE: This function does not parse properties the size of which is - * variable without a low fixed limit. Please use - * v4l2_of_alloc_parse_endpoint() in new drivers instead. - * - * Return: 0 on success or a negative error code on failure. - */ -int v4l2_of_parse_endpoint(const struct device_node *node, - struct v4l2_of_endpoint *endpoint) -{ - int rval; - - of_graph_parse_endpoint(node, &endpoint->base); - /* Zero fields from bus_type to until the end */ - memset(&endpoint->bus_type, 0, sizeof(*endpoint) - - offsetof(typeof(*endpoint), bus_type)); - - rval = v4l2_of_parse_csi_bus(node, endpoint); - if (rval) - return rval; - /* - * Parse the parallel video bus properties only if none - * of the MIPI CSI-2 specific properties were found. - */ - if (endpoint->bus.mipi_csi2.flags == 0) - v4l2_of_parse_parallel_bus(node, endpoint); - - return 0; -} -EXPORT_SYMBOL(v4l2_of_parse_endpoint); - -/* - * v4l2_of_free_endpoint() - free the endpoint acquired by - * v4l2_of_alloc_parse_endpoint() - * @endpoint - the endpoint the resources of which are to be released - * - * It is safe to call this function with NULL argument or on an - * endpoint the parsing of which failed. - */ -void v4l2_of_free_endpoint(struct v4l2_of_endpoint *endpoint) -{ - if (IS_ERR_OR_NULL(endpoint)) - return; - - kfree(endpoint->link_frequencies); - kfree(endpoint); -} -EXPORT_SYMBOL(v4l2_of_free_endpoint); - -/** - * v4l2_of_alloc_parse_endpoint() - parse all endpoint node properties - * @node: pointer to endpoint device_node - * - * All properties are optional. If none are found, we don't set any flags. - * This means the port has a static configuration and no properties have - * to be specified explicitly. - * If any properties that identify the bus as parallel are found and - * slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if we recognise - * the bus as serial CSI-2 and clock-noncontinuous isn't set, we set the - * V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. - * The caller should hold a reference to @node. - * - * v4l2_of_alloc_parse_endpoint() has two important differences to - * v4l2_of_parse_endpoint(): - * - * 1. It also parses variable size data and - * - * 2. The memory it has allocated to store the variable size data must - * be freed using v4l2_of_free_endpoint() when no longer needed. - * - * Return: Pointer to v4l2_of_endpoint if successful, on error a - * negative error code. - */ -struct v4l2_of_endpoint *v4l2_of_alloc_parse_endpoint( - const struct device_node *node) -{ - struct v4l2_of_endpoint *endpoint; - int len; - int rval; - - endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL); - if (!endpoint) - return ERR_PTR(-ENOMEM); - - rval = v4l2_of_parse_endpoint(node, endpoint); - if (rval < 0) - goto out_err; - - if (of_get_property(node, "link-frequencies", &len)) { - endpoint->link_frequencies = kmalloc(len, GFP_KERNEL); - if (!endpoint->link_frequencies) { - rval = -ENOMEM; - goto out_err; - } - - endpoint->nr_of_link_frequencies = - len / sizeof(*endpoint->link_frequencies); - - rval = of_property_read_u64_array( - node, "link-frequencies", endpoint->link_frequencies, - endpoint->nr_of_link_frequencies); - if (rval < 0) - goto out_err; - } - - return endpoint; - -out_err: - v4l2_of_free_endpoint(endpoint); - return ERR_PTR(rval); -} -EXPORT_SYMBOL(v4l2_of_alloc_parse_endpoint); - -/** - * v4l2_of_parse_link() - parse a link between two endpoints - * @node: pointer to the endpoint at the local end of the link - * @link: pointer to the V4L2 OF link data structure - * - * Fill the link structure with the local and remote nodes and port numbers. - * The local_node and remote_node fields are set to point to the local and - * remote port's parent nodes respectively (the port parent node being the - * parent node of the port node if that node isn't a 'ports' node, or the - * grand-parent node of the port node otherwise). - * - * A reference is taken to both the local and remote nodes, the caller must use - * v4l2_of_put_link() to drop the references when done with the link. - * - * Return: 0 on success, or -ENOLINK if the remote endpoint can't be found. - */ -int v4l2_of_parse_link(const struct device_node *node, - struct v4l2_of_link *link) -{ - struct device_node *np; - - memset(link, 0, sizeof(*link)); - - np = of_get_parent(node); - of_property_read_u32(np, "reg", &link->local_port); - np = of_get_next_parent(np); - if (of_node_cmp(np->name, "ports") == 0) - np = of_get_next_parent(np); - link->local_node = np; - - np = of_parse_phandle(node, "remote-endpoint", 0); - if (!np) { - of_node_put(link->local_node); - return -ENOLINK; - } - - np = of_get_parent(np); - of_property_read_u32(np, "reg", &link->remote_port); - np = of_get_next_parent(np); - if (of_node_cmp(np->name, "ports") == 0) - np = of_get_next_parent(np); - link->remote_node = np; - - return 0; -} -EXPORT_SYMBOL(v4l2_of_parse_link); - -/** - * v4l2_of_put_link() - drop references to nodes in a link - * @link: pointer to the V4L2 OF link data structure - * - * Drop references to the local and remote nodes in the link. This function must - * be called on every link parsed with v4l2_of_parse_link(). - */ -void v4l2_of_put_link(struct v4l2_of_link *link) -{ - of_node_put(link->local_node); - of_node_put(link->remote_node); -} -EXPORT_SYMBOL(v4l2_of_put_link); diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 94afbbf92807..c0175ea7e7ad 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -868,7 +868,7 @@ EXPORT_SYMBOL_GPL(vb2_core_create_bufs); void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no) { - if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv) + if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv) return NULL; return call_ptr_memop(vb, vaddr, vb->planes[plane_no].mem_priv); diff --git a/drivers/staging/media/atomisp/i2c/Makefile b/drivers/staging/media/atomisp/i2c/Makefile index 466517c7c8e6..a1afca6ec31f 100644 --- a/drivers/staging/media/atomisp/i2c/Makefile +++ b/drivers/staging/media/atomisp/i2c/Makefile @@ -19,3 +19,7 @@ obj-$(CONFIG_VIDEO_AP1302) += ap1302.o obj-$(CONFIG_VIDEO_LM3554) += lm3554.o +# HACK! While this driver is in bad shape, don't enable several warnings +# that would be otherwise enabled with W=1 +ccflags-y += -Wno-unused-but-set-variable -Wno-missing-prototypes \ + -Wno-unused-const-variable -Wno-missing-declarations diff --git a/drivers/staging/media/atomisp/i2c/imx/Makefile b/drivers/staging/media/atomisp/i2c/imx/Makefile index 6b13a3a66e49..0eceb7374bec 100644 --- a/drivers/staging/media/atomisp/i2c/imx/Makefile +++ b/drivers/staging/media/atomisp/i2c/imx/Makefile @@ -4,3 +4,8 @@ imx1x5-objs := imx.o drv201.o ad5816g.o dw9714.o dw9719.o dw9718.o vcm.o otp.o o ov8858_driver-objs := ../ov8858.o dw9718.o vcm.o obj-$(CONFIG_VIDEO_OV8858) += ov8858_driver.o + +# HACK! While this driver is in bad shape, don't enable several warnings +# that would be otherwise enabled with W=1 +ccflags-y += -Wno-unused-but-set-variable -Wno-missing-prototypes \ + -Wno-unused-const-variable -Wno-missing-declarations diff --git a/drivers/staging/media/atomisp/i2c/ov5693/Makefile b/drivers/staging/media/atomisp/i2c/ov5693/Makefile index c9c0e1245858..fd2ef2e3c31e 100644 --- a/drivers/staging/media/atomisp/i2c/ov5693/Makefile +++ b/drivers/staging/media/atomisp/i2c/ov5693/Makefile @@ -1 +1,6 @@ obj-$(CONFIG_VIDEO_OV5693) += ov5693.o + +# HACK! While this driver is in bad shape, don't enable several warnings +# that would be otherwise enabled with W=1 +ccflags-y += -Wno-unused-but-set-variable -Wno-missing-prototypes \ + -Wno-unused-const-variable -Wno-missing-declarations diff --git a/drivers/staging/media/atomisp/pci/atomisp2/Makefile b/drivers/staging/media/atomisp/pci/atomisp2/Makefile index f126a89a08e9..68a9ab1c3b61 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/Makefile +++ b/drivers/staging/media/atomisp/pci/atomisp2/Makefile @@ -353,3 +353,9 @@ DEFINES += -DSYSTEM_hive_isp_css_2400_system -DISP2400 ccflags-y += $(INCLUDES) $(DEFINES) -fno-common +# HACK! While this driver is in bad shape, don't enable several warnings +# that would be otherwise enabled with W=1 +ccflags-y += -Wno-unused-const-variable -Wno-missing-prototypes \ + -Wno-unused-but-set-variable -Wno-missing-declarations \ + -Wno-suggest-attribute=format -Wno-missing-prototypes \ + -Wno-implicit-fallthrough diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c index b830b241e2e6..ad2c610d2ce3 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c @@ -2506,7 +2506,6 @@ static void __configure_capture_pp_input(struct atomisp_sub_device *asd, struct ia_css_pipe_extra_config *pipe_extra_configs = &stream_env->pipe_extra_configs[pipe_id]; unsigned int hor_ds_factor = 0, ver_ds_factor = 0; -#define CEIL_DIV(a, b) ((b) ? ((a) + (b) - 1) / (b) : 0) if (width == 0 && height == 0) return; diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c index 7ce8803cf6f9..c151c848cf8f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c @@ -130,9 +130,9 @@ static int atomisp_q_one_metadata_buffer(struct atomisp_sub_device *asd, return 0; } -int atomisp_q_one_s3a_buffer(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - enum atomisp_css_pipe_id css_pipe_id) +static int atomisp_q_one_s3a_buffer(struct atomisp_sub_device *asd, + enum atomisp_input_stream_id stream_id, + enum atomisp_css_pipe_id css_pipe_id) { struct atomisp_s3a_buf *s3a_buf; struct list_head *s3a_list; @@ -172,9 +172,9 @@ int atomisp_q_one_s3a_buffer(struct atomisp_sub_device *asd, return 0; } -int atomisp_q_one_dis_buffer(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - enum atomisp_css_pipe_id css_pipe_id) +static int atomisp_q_one_dis_buffer(struct atomisp_sub_device *asd, + enum atomisp_input_stream_id stream_id, + enum atomisp_css_pipe_id css_pipe_id) { struct atomisp_dis_buf *dis_buf; unsigned long irqflags; @@ -744,7 +744,7 @@ static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd) /* * file operation functions */ -unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd) +static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd) { return asd->video_out_preview.users + asd->video_out_vf.users + diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_tpg.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_tpg.c index 996d1bdebad4..48b96048cab4 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_tpg.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_tpg.c @@ -56,6 +56,7 @@ static int tpg_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_format *format) { struct v4l2_mbus_framefmt *fmt = &format->format; + if (format->pad) return -EINVAL; /* only raw8 grbg is supported by TPG */ diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_v4l2.c index e3fdbdba0b34..a0478077a012 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_v4l2.c @@ -51,7 +51,7 @@ /* G-Min addition: pull this in from intel_mid_pm.h */ #define CSTATE_EXIT_LATENCY_C1 1 -static uint skip_fwload = 0; +static uint skip_fwload; module_param(skip_fwload, uint, 0644); MODULE_PARM_DESC(skip_fwload, "Skip atomisp firmware load"); diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_include/math_support.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_include/math_support.h index 48d84bc0ad9e..f74b405b0f39 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_include/math_support.h +++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_include/math_support.h @@ -62,15 +62,15 @@ #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #ifdef ISP2401 -#define ROUND_DIV(a, b) ((b) ? ((a) + ((b) >> 1)) / (b) : 0) +#define ROUND_DIV(a, b) (((b) != 0) ? ((a) + ((b) >> 1)) / (b) : 0) #endif -#define CEIL_DIV(a, b) ((b) ? ((a) + (b) - 1) / (b) : 0) +#define CEIL_DIV(a, b) (((b) != 0) ? ((a) + (b) - 1) / (b) : 0) #define CEIL_MUL(a, b) (CEIL_DIV(a, b) * (b)) #define CEIL_MUL2(a, b) (((a) + (b) - 1) & ~((b) - 1)) #define CEIL_SHIFT(a, b) (((a) + (1 << (b)) - 1)>>(b)) #define CEIL_SHIFT_MUL(a, b) (CEIL_SHIFT(a, b) << (b)) #ifdef ISP2401 -#define ROUND_HALF_DOWN_DIV(a, b) ((b) ? ((a) + (b / 2) - 1) / (b) : 0) +#define ROUND_HALF_DOWN_DIV(a, b) (((b) != 0) ? ((a) + (b / 2) - 1) / (b) : 0) #define ROUND_HALF_DOWN_MUL(a, b) (ROUND_HALF_DOWN_DIV(a, b) * (b)) #endif diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_include/string_support.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_include/string_support.h index 568631698a3d..c53241a7a281 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_include/string_support.h +++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_include/string_support.h @@ -72,9 +72,8 @@ static size_t strnlen_s( return 0; } - for (ix=0; - ((src_str[ix] != '\0') && (ix< max_len)); - ++ix) /*Nothing else to do*/; + for (ix = 0; ix < max_len && src_str[ix] != '\0'; ix++) + ; /* On Error, it will return src_size == max_len*/ return ix; @@ -118,7 +117,7 @@ STORAGE_CLASS_INLINE int strncpy_s( /* dest_str is big enough for the len */ strncpy(dest_str, src_str, len); - dest_str[len+1] = '\0'; + dest_str[len] = '\0'; return 0; } @@ -158,7 +157,7 @@ STORAGE_CLASS_INLINE int strcpy_s( /* dest_str is big enough for the len */ strncpy(dest_str, src_str, len); - dest_str[len+1] = '\0'; + dest_str[len] = '\0'; return 0; } diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/sdis/sdis_1.0/ia_css_sdis.host.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/sdis/sdis_1.0/ia_css_sdis.host.c index 0daab1176865..9478c12abe89 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/sdis/sdis_1.0/ia_css_sdis.host.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/sdis/sdis_1.0/ia_css_sdis.host.c @@ -265,9 +265,9 @@ ia_css_translate_dvs_statistics( assert(isp_stats->hor_proj != NULL); assert(isp_stats->ver_proj != NULL); - IA_CSS_ENTER("hproj=%p, vproj=%p, haddr=%x, vaddr=%x", - host_stats->hor_proj, host_stats->ver_proj, - isp_stats->hor_proj, isp_stats->ver_proj); + IA_CSS_ENTER("hproj=%p, vproj=%p, haddr=%p, vaddr=%p", + host_stats->hor_proj, host_stats->ver_proj, + isp_stats->hor_proj, isp_stats->ver_proj); hor_num_isp = host_stats->grid.aligned_height; ver_num_isp = host_stats->grid.aligned_width; diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/sdis/sdis_2/ia_css_sdis2.host.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/sdis/sdis_2/ia_css_sdis2.host.c index 5a0c103e9eb7..9bccb6473154 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/sdis/sdis_2/ia_css_sdis2.host.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/sdis/sdis_2/ia_css_sdis2.host.c @@ -213,7 +213,7 @@ ia_css_translate_dvs2_statistics( "hor_coefs.even_real=%p, hor_coefs.even_imag=%p, " "ver_coefs.odd_real=%p, ver_coefs.odd_imag=%p, " "ver_coefs.even_real=%p, ver_coefs.even_imag=%p, " - "haddr=%x, vaddr=%x", + "haddr=%p, vaddr=%p", host_stats->hor_prod.odd_real, host_stats->hor_prod.odd_imag, host_stats->hor_prod.even_real, host_stats->hor_prod.even_imag, host_stats->ver_prod.odd_real, host_stats->ver_prod.odd_imag, diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c index 804c19ab4485..222a7bd7f176 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c @@ -55,7 +55,7 @@ ia_css_tnr_dump( "tnr_coef", tnr->coef); ia_css_debug_dtrace(level, "\t%-32s = %d\n", "tnr_threshold_Y", tnr->threshold_Y); - ia_css_debug_dtrace(level, "\t%-32s = %d\n" + ia_css_debug_dtrace(level, "\t%-32s = %d\n", "tnr_threshold_C", tnr->threshold_C); } diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/binary/src/binary.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/binary/src/binary.c index a8b93a756e41..ae0b229c9fb8 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/binary/src/binary.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/binary/src/binary.c @@ -1658,7 +1658,7 @@ ia_css_binary_find(struct ia_css_binary_descr *descr, candidate->internal.max_height); continue; } - if (!candidate->enable.ds && need_ds & !(xcandidate->num_output_pins > 1)) { + if (!candidate->enable.ds && need_ds && !(xcandidate->num_output_pins > 1)) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_binary_find() [%d] continue: !%d && %d\n", __LINE__, candidate->enable.ds, (int)need_ds); diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/debug/interface/ia_css_debug.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/debug/interface/ia_css_debug.h index be7df3a30c21..91c105cc6204 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/debug/interface/ia_css_debug.h +++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/debug/interface/ia_css_debug.h @@ -137,6 +137,7 @@ ia_css_debug_vdtrace(unsigned int level, const char *fmt, va_list args) sh_css_vprint(fmt, args); } +__printf(2, 3) extern void ia_css_debug_dtrace(unsigned int level, const char *fmt, ...); /*! @brief Dump sp thread's stack contents diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/debug/src/ia_css_debug.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/debug/src/ia_css_debug.c index 030810bd0878..bcc0d464084f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/debug/src/ia_css_debug.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/debug/src/ia_css_debug.c @@ -3148,8 +3148,8 @@ ia_css_debug_dump_pipe_config( ia_css_debug_dump_frame_info(&config->vf_output_info[i], "vf_output_info"); } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "acc_extension: 0x%x\n", - config->acc_extension); + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "acc_extension: %p\n", + config->acc_extension); ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "num_acc_stages: %d\n", config->num_acc_stages); ia_css_debug_dump_capture_config(&config->default_capture_config); @@ -3179,7 +3179,7 @@ ia_css_debug_dump_stream_config_source( ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "timeout: %d\n", config->source.port.timeout); ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "compression: %d\n", - config->source.port.compression); + config->source.port.compression.type); break; case IA_CSS_INPUT_MODE_TPG: ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "source.tpg\n"); diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c index 73c76583610a..81a21a0c1391 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c @@ -2003,7 +2003,7 @@ ia_css_enable_isys_event_queue(bool enable) void *sh_css_malloc(size_t size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_malloc() enter: size=%d\n",size); + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_malloc() enter: size=%zu\n",size); /* FIXME: This first test can probably go away */ if (size == 0) return NULL; @@ -2016,7 +2016,7 @@ void *sh_css_calloc(size_t N, size_t size) { void *p; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_calloc() enter: N=%d, size=%d\n",N,size); + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_calloc() enter: N=%zu, size=%zu\n",N,size); /* FIXME: this test can probably go away */ if (size > 0) { @@ -2059,7 +2059,8 @@ map_sp_threads(struct ia_css_stream *stream, bool map) enum ia_css_pipe_id pipe_id; assert(stream != NULL); - IA_CSS_ENTER_PRIVATE("stream = %p, map = %p", stream, map); + IA_CSS_ENTER_PRIVATE("stream = %p, map = %s", + stream, map ? "true" : "false"); if (stream == NULL) { IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); @@ -2766,7 +2767,7 @@ enum ia_css_err ia_css_irq_translate( *irq_infos = infos; ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_irq_translate() " - "leave: irq_infos=%p\n", infos); + "leave: irq_infos=%u\n", infos); return IA_CSS_SUCCESS; } @@ -4514,7 +4515,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe, #else if (hmm_buffer_record) { #endif - IA_CSS_LOG("send vbuf=0x%x", h_vbuf); + IA_CSS_LOG("send vbuf=%p", h_vbuf); } else { return_err = IA_CSS_ERR_INTERNAL_ERROR; IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n"); @@ -4624,7 +4625,7 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &hmm_buffer_record->h_vbuf); sh_css_hmm_buffer_record_reset(hmm_buffer_record); } else { - IA_CSS_ERROR("hmm_buffer_record not found (0x%p) buf_type(%d)", + IA_CSS_ERROR("hmm_buffer_record not found (0x%u) buf_type(%d)", ddr_buffer_addr, buf_type); IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR); return IA_CSS_ERR_INTERNAL_ERROR; @@ -4640,8 +4641,8 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, if ((ddr_buffer.kernel_ptr == 0) || (kernel_ptr != HOST_ADDRESS(ddr_buffer.kernel_ptr))) { IA_CSS_ERROR("kernel_ptr invalid"); - IA_CSS_ERROR("expected: (0x%p)", kernel_ptr); - IA_CSS_ERROR("actual: (0x%p)", HOST_ADDRESS(ddr_buffer.kernel_ptr)); + IA_CSS_ERROR("expected: (0x%llx)", (u64)kernel_ptr); + IA_CSS_ERROR("actual: (0x%llx)", (u64)HOST_ADDRESS(ddr_buffer.kernel_ptr)); IA_CSS_ERROR("buf_type: %d\n", buf_type); IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR); return IA_CSS_ERR_INTERNAL_ERROR; @@ -6621,7 +6622,7 @@ allocate_delay_frames(struct ia_css_pipe *pipe) IA_CSS_ENTER_PRIVATE(""); if (pipe == NULL) { - IA_CSS_ERROR("Invalid args - pipe %x", pipe); + IA_CSS_ERROR("Invalid args - pipe %p", pipe); return IA_CSS_ERR_INVALID_ARGUMENTS; } diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_mipi.c index 7e3893c6c08a..36aaa3019a15 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_mipi.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_mipi.c @@ -681,7 +681,7 @@ send_mipi_frames(struct ia_css_pipe *pipe) unsigned int port = 0; #endif - IA_CSS_ENTER_PRIVATE("pipe=%d", pipe); + IA_CSS_ENTER_PRIVATE("pipe=%p", pipe); assert(pipe != NULL); assert(pipe->stream != NULL); diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_params.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_params.c index 561f4a7236f7..d8c22e8cd3af 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_params.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_params.c @@ -3375,7 +3375,7 @@ enum ia_css_err ia_css_pipe_set_bci_scaler_lut(struct ia_css_pipe *pipe, #endif if (pipe->scaler_pp_lut == mmgr_NULL) { #ifndef ISP2401 - IA_CSS_LEAVE("lut(%p) err=%d", pipe->scaler_pp_lut, err); + IA_CSS_LEAVE("lut(%u) err=%d", pipe->scaler_pp_lut, err); return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; #else ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, @@ -3397,7 +3397,7 @@ enum ia_css_err ia_css_pipe_set_bci_scaler_lut(struct ia_css_pipe *pipe, #endif } - IA_CSS_LEAVE("lut(%p) err=%d", pipe->scaler_pp_lut, err); + IA_CSS_LEAVE("lut(%u) err=%d", pipe->scaler_pp_lut, err); return err; } @@ -3437,7 +3437,7 @@ enum ia_css_err sh_css_params_map_and_store_default_gdc_lut(void) mmgr_store(default_gdc_lut, (int *)interleaved_lut_temp, sizeof(zoom_table)); - IA_CSS_LEAVE_PRIVATE("lut(%p) err=%d", default_gdc_lut, err); + IA_CSS_LEAVE_PRIVATE("lut(%u) err=%d", default_gdc_lut, err); return err; } @@ -3859,7 +3859,7 @@ sh_css_param_update_isp_params(struct ia_css_pipe *curr_pipe, /* When API change is implemented making good distinction between * stream config and pipe config this skipping code can be moved out of the #ifdef */ if (pipe_in && (pipe != pipe_in)) { - IA_CSS_LOG("skipping pipe %x", pipe); + IA_CSS_LOG("skipping pipe %p", pipe); continue; } @@ -4590,7 +4590,7 @@ free_ia_css_isp_parameter_set_info( unsigned int i; hrt_vaddress *addrs = (hrt_vaddress *)&isp_params_info.mem_map; - IA_CSS_ENTER_PRIVATE("ptr = %p", ptr); + IA_CSS_ENTER_PRIVATE("ptr = %u", ptr); /* sanity check - ptr must be valid */ if (!ia_css_refcount_is_valid(ptr)) { diff --git a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c index 5b4506a71126..d68e9cf33aa7 100644 --- a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c +++ b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c @@ -51,7 +51,7 @@ struct gmin_subdev { static struct gmin_subdev gmin_subdevs[MAX_SUBDEVS]; -static enum { PMIC_UNSET = 0, PMIC_REGULATOR, PMIC_AXP, PMIC_TI , +static enum { PMIC_UNSET = 0, PMIC_REGULATOR, PMIC_AXP, PMIC_TI, PMIC_CRYSTALCOVE } pmic_id; /* The atomisp uses type==0 for the end-of-list marker, so leave space. */ @@ -119,7 +119,7 @@ static int af_power_ctrl(struct v4l2_subdev *subdev, int flag) /* * The power here is used for dw9817, * regulator is from rear sensor - */ + */ if (gs->v2p8_vcm_reg) { if (flag) return regulator_enable(gs->v2p8_vcm_reg); @@ -152,13 +152,13 @@ const struct camera_af_platform_data *camera_get_af_platform_data(void) EXPORT_SYMBOL_GPL(camera_get_af_platform_data); int atomisp_register_i2c_module(struct v4l2_subdev *subdev, - struct camera_sensor_platform_data *plat_data, - enum intel_v4l2_subdev_type type) + struct camera_sensor_platform_data *plat_data, + enum intel_v4l2_subdev_type type) { int i; struct i2c_board_info *bi; struct gmin_subdev *gs; - struct i2c_client *client = v4l2_get_subdevdata(subdev); + struct i2c_client *client = v4l2_get_subdevdata(subdev); struct acpi_device *adev; dev_info(&client->dev, "register atomisp i2c module type %d\n", type); @@ -167,12 +167,13 @@ int atomisp_register_i2c_module(struct v4l2_subdev *subdev, * uses ACPI runtime power management for camera devices, but * we don't. Disable it, or else the rails will be needlessly * tickled during suspend/resume. This has caused power and - * performance issues on multiple devices. */ + * performance issues on multiple devices. + */ adev = ACPI_COMPANION(&client->dev); if (adev) adev->power.flags.power_resources = 0; - for (i=0; i < MAX_SUBDEVS; i++) + for (i = 0; i < MAX_SUBDEVS; i++) if (!pdata.subdevs[i].type) break; @@ -182,7 +183,8 @@ int atomisp_register_i2c_module(struct v4l2_subdev *subdev, /* Note subtlety of initialization order: at the point where * this registration API gets called, the platform data * callbacks have probably already been invoked, so the - * gmin_subdev struct is already initialized for us. */ + * gmin_subdev struct is already initialized for us. + */ gs = find_gmin_subdev(subdev); pdata.subdevs[i].type = type; @@ -206,8 +208,10 @@ struct v4l2_subdev *atomisp_gmin_find_subdev(struct i2c_adapter *adapter, struct i2c_board_info *board_info) { int i; - for (i=0; i < MAX_SUBDEVS && pdata.subdevs[i].type; i++) { + + for (i = 0; i < MAX_SUBDEVS && pdata.subdevs[i].type; i++) { struct intel_v4l2_subdev_table *sd = &pdata.subdevs[i]; + if (sd->v4l2_subdev.i2c_adapter_id == adapter->nr && sd->v4l2_subdev.board_info.addr == board_info->addr) return sd->subdev; @@ -261,7 +265,8 @@ static const struct gmin_cfg_var ffrd8_vars[] = { }; /* Cribbed from MCG defaults in the mt9m114 driver, not actually verified - * vs. T100 hardware */ + * vs. T100 hardware + */ static const struct gmin_cfg_var t100_vars[] = { { "INT33F0:00_CsiPort", "0" }, { "INT33F0:00_CsiLanes", "1" }, @@ -270,45 +275,45 @@ static const struct gmin_cfg_var t100_vars[] = { }; static const struct gmin_cfg_var mrd7_vars[] = { - {"INT33F8:00_CamType", "1"}, - {"INT33F8:00_CsiPort", "1"}, - {"INT33F8:00_CsiLanes","2"}, - {"INT33F8:00_CsiFmt","13"}, - {"INT33F8:00_CsiBayer", "0"}, - {"INT33F8:00_CamClk", "0"}, - {"INT33F9:00_CamType", "1"}, - {"INT33F9:00_CsiPort", "0"}, - {"INT33F9:00_CsiLanes","1"}, - {"INT33F9:00_CsiFmt","13"}, - {"INT33F9:00_CsiBayer", "0"}, - {"INT33F9:00_CamClk", "1"}, - {}, + {"INT33F8:00_CamType", "1"}, + {"INT33F8:00_CsiPort", "1"}, + {"INT33F8:00_CsiLanes", "2"}, + {"INT33F8:00_CsiFmt", "13"}, + {"INT33F8:00_CsiBayer", "0"}, + {"INT33F8:00_CamClk", "0"}, + {"INT33F9:00_CamType", "1"}, + {"INT33F9:00_CsiPort", "0"}, + {"INT33F9:00_CsiLanes", "1"}, + {"INT33F9:00_CsiFmt", "13"}, + {"INT33F9:00_CsiBayer", "0"}, + {"INT33F9:00_CamClk", "1"}, + {}, }; static const struct gmin_cfg_var ecs7_vars[] = { - {"INT33BE:00_CsiPort", "1"}, - {"INT33BE:00_CsiLanes","2"}, - {"INT33BE:00_CsiFmt","13"}, - {"INT33BE:00_CsiBayer", "2"}, - {"INT33BE:00_CamClk", "0"}, - {"INT33F0:00_CsiPort", "0"}, - {"INT33F0:00_CsiLanes","1"}, - {"INT33F0:00_CsiFmt","13"}, - {"INT33F0:00_CsiBayer", "0"}, - {"INT33F0:00_CamClk", "1"}, - {"gmin_V2P8GPIO","402"}, - {}, + {"INT33BE:00_CsiPort", "1"}, + {"INT33BE:00_CsiLanes", "2"}, + {"INT33BE:00_CsiFmt", "13"}, + {"INT33BE:00_CsiBayer", "2"}, + {"INT33BE:00_CamClk", "0"}, + {"INT33F0:00_CsiPort", "0"}, + {"INT33F0:00_CsiLanes", "1"}, + {"INT33F0:00_CsiFmt", "13"}, + {"INT33F0:00_CsiBayer", "0"}, + {"INT33F0:00_CamClk", "1"}, + {"gmin_V2P8GPIO", "402"}, + {}, }; static const struct gmin_cfg_var i8880_vars[] = { - {"XXOV2680:00_CsiPort", "1"}, - {"XXOV2680:00_CsiLanes","1"}, - {"XXOV2680:00_CamClk","0"}, - {"XXGC0310:00_CsiPort", "0"}, - {"XXGC0310:00_CsiLanes", "1"}, - {"XXGC0310:00_CamClk", "1"}, - {}, + {"XXOV2680:00_CsiPort", "1"}, + {"XXOV2680:00_CsiLanes", "1"}, + {"XXOV2680:00_CamClk", "0"}, + {"XXGC0310:00_CsiPort", "0"}, + {"XXGC0310:00_CsiLanes", "1"}, + {"XXGC0310:00_CamClk", "1"}, + {}, }; static const struct { @@ -317,9 +322,9 @@ static const struct { } hard_vars[] = { { "BYT-T FFD8", ffrd8_vars }, { "T100TA", t100_vars }, - { "MRD7", mrd7_vars }, - { "ST70408", ecs7_vars }, - { "VTA0803", i8880_vars }, + { "MRD7", mrd7_vars }, + { "ST70408", ecs7_vars }, + { "VTA0803", i8880_vars }, }; @@ -343,19 +348,17 @@ static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev) { int i, ret; struct device *dev; - struct i2c_client *client = v4l2_get_subdevdata(subdev); - - if (!pmic_id) { + struct i2c_client *client = v4l2_get_subdevdata(subdev); - pmic_id = PMIC_REGULATOR; - } + if (!pmic_id) + pmic_id = PMIC_REGULATOR; if (!client) return NULL; dev = &client->dev; - for (i=0; i < MAX_SUBDEVS && gmin_subdevs[i].subdev; i++) + for (i = 0; i < MAX_SUBDEVS && gmin_subdevs[i].subdev; i++) ; if (i >= MAX_SUBDEVS) return NULL; @@ -401,7 +404,8 @@ static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev) * API is broken with the current drivers, returning * "1" for a regulator that will then emit a * "unbalanced disable" WARNing if we try to disable - * it. */ + * it. + */ } return &gmin_subdevs[i]; @@ -410,7 +414,8 @@ static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev) static struct gmin_subdev *find_gmin_subdev(struct v4l2_subdev *subdev) { int i; - for (i=0; i < MAX_SUBDEVS; i++) + + for (i = 0; i < MAX_SUBDEVS; i++) if (gmin_subdevs[i].subdev == subdev) return &gmin_subdevs[i]; return gmin_subdev_add(subdev); @@ -419,6 +424,7 @@ static struct gmin_subdev *find_gmin_subdev(struct v4l2_subdev *subdev) static int gmin_gpio0_ctrl(struct v4l2_subdev *subdev, int on) { struct gmin_subdev *gs = find_gmin_subdev(subdev); + if (gs && gs->gpio0) { gpiod_set_value(gs->gpio0, on); return 0; @@ -429,6 +435,7 @@ static int gmin_gpio0_ctrl(struct v4l2_subdev *subdev, int on) static int gmin_gpio1_ctrl(struct v4l2_subdev *subdev, int on) { struct gmin_subdev *gs = find_gmin_subdev(subdev); + if (gs && gs->gpio1) { gpiod_set_value(gs->gpio1, on); return 0; @@ -436,7 +443,7 @@ static int gmin_gpio1_ctrl(struct v4l2_subdev *subdev, int on) return -EINVAL; } -int gmin_v1p2_ctrl(struct v4l2_subdev *subdev, int on) +static int gmin_v1p2_ctrl(struct v4l2_subdev *subdev, int on) { struct gmin_subdev *gs = find_gmin_subdev(subdev); @@ -455,7 +462,8 @@ int gmin_v1p2_ctrl(struct v4l2_subdev *subdev, int on) return -EINVAL; } -int gmin_v1p8_ctrl(struct v4l2_subdev *subdev, int on) + +static int gmin_v1p8_ctrl(struct v4l2_subdev *subdev, int on) { struct gmin_subdev *gs = find_gmin_subdev(subdev); int ret; @@ -481,7 +489,7 @@ int gmin_v1p8_ctrl(struct v4l2_subdev *subdev, int on) gpio_set_value(v1p8_gpio, on); if (gs->v1p8_reg) { - regulator_set_voltage(gs->v1p8_reg, 1800000, 1800000); + regulator_set_voltage(gs->v1p8_reg, 1800000, 1800000); if (on) return regulator_enable(gs->v1p8_reg); else @@ -491,7 +499,7 @@ int gmin_v1p8_ctrl(struct v4l2_subdev *subdev, int on) return -EINVAL; } -int gmin_v2p8_ctrl(struct v4l2_subdev *subdev, int on) +static int gmin_v2p8_ctrl(struct v4l2_subdev *subdev, int on) { struct gmin_subdev *gs = find_gmin_subdev(subdev); int ret; @@ -517,7 +525,7 @@ int gmin_v2p8_ctrl(struct v4l2_subdev *subdev, int on) gpio_set_value(v2p8_gpio, on); if (gs->v2p8_reg) { - regulator_set_voltage(gs->v2p8_reg, 2900000, 2900000); + regulator_set_voltage(gs->v2p8_reg, 2900000, 2900000); if (on) return regulator_enable(gs->v2p8_reg); else @@ -527,10 +535,11 @@ int gmin_v2p8_ctrl(struct v4l2_subdev *subdev, int on) return -EINVAL; } -int gmin_flisclk_ctrl(struct v4l2_subdev *subdev, int on) +static int gmin_flisclk_ctrl(struct v4l2_subdev *subdev, int on) { int ret = 0; struct gmin_subdev *gs = find_gmin_subdev(subdev); + if (on) ret = vlv2_plat_set_clock_freq(gs->clock_num, gs->clock_src); if (ret) @@ -595,6 +604,7 @@ struct camera_sensor_platform_data *gmin_camera_platform_data( enum atomisp_bayer_order csi_bayer) { struct gmin_subdev *gs = find_gmin_subdev(subdev); + gs->csi_fmt = csi_format; gs->csi_bayer = csi_bayer; @@ -617,8 +627,10 @@ EXPORT_SYMBOL_GPL(atomisp_gmin_register_vcm_control); /* Retrieves a device-specific configuration variable. The dev * argument should be a device with an ACPI companion, as all - * configuration is based on firmware ID. */ -int gmin_get_config_var(struct device *dev, const char *var, char *out, size_t *out_len) + * configuration is based on firmware ID. + */ +int gmin_get_config_var(struct device *dev, const char *var, char *out, + size_t *out_len) { char var8[CFG_VAR_NAME_MAX]; efi_char16_t var16[CFG_VAR_NAME_MAX]; @@ -627,20 +639,21 @@ int gmin_get_config_var(struct device *dev, const char *var, char *out, size_t * int i, j, ret; unsigned long efilen; - if (dev && ACPI_COMPANION(dev)) - dev = &ACPI_COMPANION(dev)->dev; + if (dev && ACPI_COMPANION(dev)) + dev = &ACPI_COMPANION(dev)->dev; - if (dev) - ret = snprintf(var8, sizeof(var8), "%s_%s", dev_name(dev), var); - else - ret = snprintf(var8, sizeof(var8), "gmin_%s", var); + if (dev) + ret = snprintf(var8, sizeof(var8), "%s_%s", dev_name(dev), var); + else + ret = snprintf(var8, sizeof(var8), "gmin_%s", var); if (ret < 0 || ret >= sizeof(var8) - 1) return -EINVAL; /* First check a hard-coded list of board-specific variables. * Some device firmwares lack the ability to set EFI variables at - * runtime. */ + * runtime. + */ for (i = 0; i < ARRAY_SIZE(hard_vars); i++) { if (dmi_match(DMI_BOARD_NAME, hard_vars[i].dmi_board_name)) { for (j = 0; hard_vars[i].vars[j].name; j++) { @@ -665,7 +678,8 @@ int gmin_get_config_var(struct device *dev, const char *var, char *out, size_t * } /* Our variable names are ASCII by construction, but EFI names - * are wide chars. Convert and zero-pad. */ + * are wide chars. Convert and zero-pad. + */ memset(var16, 0, sizeof(var16)); for (i = 0; i < sizeof(var8) && var8[i]; i++) var16[i] = var8[i]; @@ -678,7 +692,8 @@ int gmin_get_config_var(struct device *dev, const char *var, char *out, size_t * * implementation simply uses VariableName and VendorGuid from * the struct and ignores the rest, but it seems like there * ought to be an "official" efivar_entry registered - * somewhere? */ + * somewhere? + */ ev = kzalloc(sizeof(*ev), GFP_KERNEL); if (!ev) return -ENOMEM; @@ -692,7 +707,7 @@ int gmin_get_config_var(struct device *dev, const char *var, char *out, size_t * *out_len = efilen; if (ret) - dev_warn(dev, "Failed to find gmin variable %s\n", var8); + dev_warn(dev, "Failed to find gmin variable %s\n", var8); return ret; } @@ -718,38 +733,39 @@ EXPORT_SYMBOL_GPL(gmin_get_var_int); int camera_sensor_csi(struct v4l2_subdev *sd, u32 port, u32 lanes, u32 format, u32 bayer_order, int flag) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct camera_mipi_info *csi = NULL; - - if (flag) { - csi = kzalloc(sizeof(*csi), GFP_KERNEL); - if (!csi) { - dev_err(&client->dev, "out of memory\n"); - return -ENOMEM; - } - csi->port = port; - csi->num_lanes = lanes; - csi->input_format = format; - csi->raw_bayer_order = bayer_order; - v4l2_set_subdev_hostdata(sd, (void *)csi); - csi->metadata_format = ATOMISP_INPUT_FORMAT_EMBEDDED; - csi->metadata_effective_width = NULL; - dev_info(&client->dev, - "camera pdata: port: %d lanes: %d order: %8.8x\n", - port, lanes, bayer_order); - } else { - csi = v4l2_get_subdev_hostdata(sd); - kfree(csi); - } - - return 0; + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct camera_mipi_info *csi = NULL; + + if (flag) { + csi = kzalloc(sizeof(*csi), GFP_KERNEL); + if (!csi) { + dev_err(&client->dev, "out of memory\n"); + return -ENOMEM; + } + csi->port = port; + csi->num_lanes = lanes; + csi->input_format = format; + csi->raw_bayer_order = bayer_order; + v4l2_set_subdev_hostdata(sd, (void *)csi); + csi->metadata_format = ATOMISP_INPUT_FORMAT_EMBEDDED; + csi->metadata_effective_width = NULL; + dev_info(&client->dev, + "camera pdata: port: %d lanes: %d order: %8.8x\n", + port, lanes, bayer_order); + } else { + csi = v4l2_get_subdev_hostdata(sd); + kfree(csi); + } + + return 0; } EXPORT_SYMBOL_GPL(camera_sensor_csi); /* PCI quirk: The BYT ISP advertises PCI runtime PM but it doesn't * work. Disable so the kernel framework doesn't hang the device * trying. The driver itself does direct calls to the PUNIT to manage - * ISP power. */ + * ISP power. + */ static void isp_pm_cap_fixup(struct pci_dev *dev) { dev_info(&dev->dev, "Disabling PCI power management on camera ISP\n"); diff --git a/drivers/staging/media/atomisp/platform/intel-mid/intel_mid_pcihelpers.c b/drivers/staging/media/atomisp/platform/intel-mid/intel_mid_pcihelpers.c index a6c0f5f8c3f8..cd452cc20fea 100644 --- a/drivers/staging/media/atomisp/platform/intel-mid/intel_mid_pcihelpers.c +++ b/drivers/staging/media/atomisp/platform/intel-mid/intel_mid_pcihelpers.c @@ -5,7 +5,8 @@ /* G-Min addition: "platform_is()" lives in intel_mid_pm.h in the MCG * tree, but it's just platform ID info and we don't want to pull in - * the whole SFI-based PM architecture. */ + * the whole SFI-based PM architecture. + */ #define INTEL_ATOM_MRST 0x26 #define INTEL_ATOM_MFLD 0x27 #define INTEL_ATOM_CLV 0x35 @@ -22,7 +23,7 @@ #endif static inline int platform_is(u8 model) { - return (boot_cpu_data.x86_model == model); + return (boot_cpu_data.x86_model == model); } #include "../../include/asm/intel_mid_pcihelpers.h" @@ -32,7 +33,6 @@ static DEFINE_SPINLOCK(msgbus_lock); static struct pci_dev *pci_root; static struct pm_qos_request pm_qos; -int qos; #define DW_I2C_NEED_QOS (platform_is(INTEL_ATOM_BYT)) @@ -136,8 +136,8 @@ u32 intel_mid_msgbus_read32(u8 port, u32 addr) return data; } - EXPORT_SYMBOL(intel_mid_msgbus_read32); + void intel_mid_msgbus_write32(u8 port, u32 addr, u32 data) { unsigned long irq_flags; @@ -171,8 +171,8 @@ EXPORT_SYMBOL(intel_mid_soc_stepping); static bool is_south_complex_device(struct pci_dev *dev) { - unsigned base_class = dev->class >> 16; - unsigned sub_class = (dev->class & SUB_CLASS_MASK) >> 8; + unsigned int base_class = dev->class >> 16; + unsigned int sub_class = (dev->class & SUB_CLASS_MASK) >> 8; /* other than camera, pci bridges and display, * everything else are south complex devices. diff --git a/drivers/staging/media/lirc/TODO b/drivers/staging/media/lirc/TODO index cbea5d84fed3..a97800a8e127 100644 --- a/drivers/staging/media/lirc/TODO +++ b/drivers/staging/media/lirc/TODO @@ -1,13 +1,36 @@ -- All drivers should either be ported to ir-core, or dropped entirely - (see drivers/media/IR/mceusb.c vs. lirc_mceusb.c in lirc cvs for an - example of a previously completed port). - -- lirc_bt829 uses registers on a Mach64 VT, which has a separate kernel - framebuffer driver (atyfb) and userland X driver (mach64). It can't - simply be converted to a normal PCI driver, but ideally it should be - coordinated with the other drivers. - -Please send patches to: -Jarod Wilson <jarod@wilsonet.com> -Greg Kroah-Hartman <greg@kroah.com> +1. Both ir-kbd-i2c and lirc_zilog provide support for RX events for +the chips supported by lirc_zilog. Before moving lirc_zilog out of staging: + +a. ir-kbd-i2c needs a module parameter added to allow the user to tell + ir-kbd-i2c to ignore Z8 IR units. + +b. lirc_zilog should provide Rx key presses to the rc core like ir-kbd-i2c + does. + + +2. lirc_zilog module ref-counting need examination. It has not been +verified that cdev and lirc_dev will take the proper module references on +lirc_zilog to prevent removal of lirc_zilog when the /dev/lircN device node +is open. + +(The good news is ref-counting of lirc_zilog internal structures appears to be +complete. Testing has shown the cx18 module can be unloaded out from under +irw + lircd + lirc_dev, with the /dev/lirc0 device node open, with no adverse +effects. The cx18 module could then be reloaded and irw properly began +receiving button presses again and ir_send worked without error.) + + +3. Bridge drivers, if able, should provide a chip reset() callback +to lirc_zilog via struct IR_i2c_init_data. cx18 and ivtv already have routines +to perform Z8 chip resets via GPIO manipulations. This would allow lirc_zilog +to bring the chip back to normal when it hangs, in the same places the +original lirc_pvr150 driver code does. This is not strictly needed, so it +is not required to move lirc_zilog out of staging. + +Note: Both lirc_zilog and ir-kbd-i2c support the Zilog Z8 for IR, as programmed +and installed on Hauppauge products. When working on either module, developers +must consider at least the following bridge drivers which mention an IR Rx unit +at address 0x71 (indicative of a Z8): + + ivtv cx18 hdpvr pvrusb2 bt8xx cx88 saa7134 diff --git a/drivers/staging/media/lirc/TODO.lirc_zilog b/drivers/staging/media/lirc/TODO.lirc_zilog deleted file mode 100644 index a97800a8e127..000000000000 --- a/drivers/staging/media/lirc/TODO.lirc_zilog +++ /dev/null @@ -1,36 +0,0 @@ -1. Both ir-kbd-i2c and lirc_zilog provide support for RX events for -the chips supported by lirc_zilog. Before moving lirc_zilog out of staging: - -a. ir-kbd-i2c needs a module parameter added to allow the user to tell - ir-kbd-i2c to ignore Z8 IR units. - -b. lirc_zilog should provide Rx key presses to the rc core like ir-kbd-i2c - does. - - -2. lirc_zilog module ref-counting need examination. It has not been -verified that cdev and lirc_dev will take the proper module references on -lirc_zilog to prevent removal of lirc_zilog when the /dev/lircN device node -is open. - -(The good news is ref-counting of lirc_zilog internal structures appears to be -complete. Testing has shown the cx18 module can be unloaded out from under -irw + lircd + lirc_dev, with the /dev/lirc0 device node open, with no adverse -effects. The cx18 module could then be reloaded and irw properly began -receiving button presses again and ir_send worked without error.) - - -3. Bridge drivers, if able, should provide a chip reset() callback -to lirc_zilog via struct IR_i2c_init_data. cx18 and ivtv already have routines -to perform Z8 chip resets via GPIO manipulations. This would allow lirc_zilog -to bring the chip back to normal when it hangs, in the same places the -original lirc_pvr150 driver code does. This is not strictly needed, so it -is not required to move lirc_zilog out of staging. - -Note: Both lirc_zilog and ir-kbd-i2c support the Zilog Z8 for IR, as programmed -and installed on Hauppauge products. When working on either module, developers -must consider at least the following bridge drivers which mention an IR Rx unit -at address 0x71 (indicative of a Z8): - - ivtv cx18 hdpvr pvrusb2 bt8xx cx88 saa7134 - diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index 8ce1db04414a..015e41bd036e 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -156,7 +156,6 @@ static struct mutex tx_data_lock; /* module parameters */ static bool debug; /* debug output */ static bool tx_only; /* only handle the IR Tx function */ -static int minor = -1; /* minor number */ /* struct IR reference counting */ @@ -184,10 +183,11 @@ static void release_ir_device(struct kref *ref) * ir->open_count == 0 - happens on final close() * ir_lock, tx_ref_lock, rx_ref_lock, all released */ - if (ir->l.minor >= 0 && ir->l.minor < MAX_IRCTL_DEVICES) { + if (ir->l.minor >= 0) { lirc_unregister_driver(ir->l.minor); - ir->l.minor = MAX_IRCTL_DEVICES; + ir->l.minor = -1; } + if (kfifo_initialized(&ir->rbuf.fifo)) lirc_buffer_free(&ir->rbuf); list_del(&ir->list); @@ -215,7 +215,7 @@ static struct IR_rx *get_ir_rx(struct IR *ir) spin_lock(&ir->rx_ref_lock); rx = ir->rx; - if (rx != NULL) + if (rx) kref_get(&rx->ref); spin_unlock(&ir->rx_ref_lock); return rx; @@ -277,7 +277,7 @@ static struct IR_tx *get_ir_tx(struct IR *ir) spin_lock(&ir->tx_ref_lock); tx = ir->tx; - if (tx != NULL) + if (tx) kref_get(&tx->ref); spin_unlock(&ir->tx_ref_lock); return tx; @@ -327,12 +327,12 @@ static int add_to_buf(struct IR *ir) } rx = get_ir_rx(ir); - if (rx == NULL) + if (!rx) return -ENXIO; /* Ensure our rx->c i2c_client remains valid for the duration */ mutex_lock(&rx->client_lock); - if (rx->c == NULL) { + if (!rx->c) { mutex_unlock(&rx->client_lock); put_ir_rx(rx, false); return -ENXIO; @@ -388,7 +388,7 @@ static int add_to_buf(struct IR *ir) break; } schedule_timeout((100 * HZ + 999) / 1000); - if (tx != NULL) + if (tx) tx->need_boot = 1; ++failures; @@ -444,7 +444,7 @@ static int add_to_buf(struct IR *ir) } while (!lirc_buffer_full(rbuf)); mutex_unlock(&rx->client_lock); - if (tx != NULL) + if (tx) put_ir_tx(tx, false); put_ir_rx(rx, false); return ret; @@ -472,7 +472,7 @@ static int lirc_thread(void *arg) /* if device not opened, we can sleep half a second */ if (atomic_read(&ir->open_count) == 0) { - schedule_timeout(HZ/2); + schedule_timeout(HZ / 2); continue; } @@ -497,18 +497,9 @@ static int lirc_thread(void *arg) return 0; } -static int set_use_inc(void *data) -{ - return 0; -} - -static void set_use_dec(void *data) -{ -} - /* safe read of a uint32 (always network byte order) */ static int read_uint32(unsigned char **data, - unsigned char *endp, unsigned int *val) + unsigned char *endp, unsigned int *val) { if (*data + 4 > endp) return 0; @@ -520,7 +511,7 @@ static int read_uint32(unsigned char **data, /* safe read of a uint8 */ static int read_uint8(unsigned char **data, - unsigned char *endp, unsigned char *val) + unsigned char *endp, unsigned char *val) { if (*data + 1 > endp) return 0; @@ -530,7 +521,7 @@ static int read_uint8(unsigned char **data, /* safe skipping of N bytes */ static int skip(unsigned char **data, - unsigned char *endp, unsigned int distance) + unsigned char *endp, unsigned int distance) { if (*data + distance > endp) return 0; @@ -540,7 +531,7 @@ static int skip(unsigned char **data, /* decompress key data into the given buffer */ static int get_key_data(unsigned char *buf, - unsigned int codeset, unsigned int key) + unsigned int codeset, unsigned int key) { unsigned char *data, *endp, *diffs, *key_block; unsigned char keys, ndiffs, id; @@ -554,9 +545,9 @@ static int get_key_data(unsigned char *buf, if (!read_uint32(&data, tx_data->endp, &i)) goto corrupt; - if (i == codeset) + if (i == codeset) { break; - else if (codeset > i) { + } else if (codeset > i) { base = pos + 1; --lim; } @@ -772,7 +763,7 @@ static int fw_load(struct IR_tx *tx) /* Parse the file */ tx_data = vmalloc(sizeof(*tx_data)); - if (tx_data == NULL) { + if (!tx_data) { release_firmware(fw_entry); ret = -ENOMEM; goto out; @@ -781,7 +772,7 @@ static int fw_load(struct IR_tx *tx) /* Copy the data so hotplug doesn't get confused and timeout */ tx_data->datap = vmalloc(fw_entry->size); - if (tx_data->datap == NULL) { + if (!tx_data->datap) { release_firmware(fw_entry); vfree(tx_data); ret = -ENOMEM; @@ -810,7 +801,7 @@ static int fw_load(struct IR_tx *tx) goto corrupt; if (!read_uint32(&data, tx_data->endp, - &tx_data->num_code_sets)) + &tx_data->num_code_sets)) goto corrupt; dev_dbg(tx->ir->l.dev, "%u IR blaster codesets loaded\n", @@ -818,7 +809,7 @@ static int fw_load(struct IR_tx *tx) tx_data->code_sets = vmalloc( tx_data->num_code_sets * sizeof(char *)); - if (tx_data->code_sets == NULL) { + if (!tx_data->code_sets) { fw_unload_locked(); ret = -ENOMEM; goto out; @@ -866,12 +857,12 @@ static int fw_load(struct IR_tx *tx) * global fixed */ if (!skip(&data, tx_data->endp, - 1 + TX_BLOCK_SIZE - num_global_fixed)) + 1 + TX_BLOCK_SIZE - num_global_fixed)) goto corrupt; /* Then we have keys-1 blocks of key id+diffs */ if (!skip(&data, tx_data->endp, - (ndiffs + 1) * (keys - 1))) + (ndiffs + 1) * (keys - 1))) goto corrupt; } ret = 0; @@ -905,7 +896,7 @@ static ssize_t read(struct file *filep, char __user *outbuf, size_t n, } rx = get_ir_rx(ir); - if (rx == NULL) + if (!rx) return -ENXIO; /* @@ -990,8 +981,9 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key) "failed to get data for code %u, key %u -- check lircd.conf entries\n", code, key); return ret; - } else if (ret != 0) + } else if (ret != 0) { return ret; + } /* Send the data block */ ret = send_data_block(tx, data_block); @@ -1065,7 +1057,7 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key) break; dev_dbg(tx->ir->l.dev, "NAK expected: i2c_master_send failed with %d (try %d)\n", - ret, i+1); + ret, i + 1); } if (ret != 1) { dev_err(tx->ir->l.dev, @@ -1111,12 +1103,12 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n, /* Get a struct IR_tx reference */ tx = get_ir_tx(ir); - if (tx == NULL) + if (!tx) return -ENXIO; /* Ensure our tx->c i2c_client remains valid for the duration */ mutex_lock(&tx->client_lock); - if (tx->c == NULL) { + if (!tx->c) { mutex_unlock(&tx->client_lock); put_ir_tx(tx, false); return -ENXIO; @@ -1188,8 +1180,9 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n, schedule_timeout((100 * HZ + 999) / 1000); tx->need_boot = 1; ++failures; - } else + } else { i += sizeof(int); + } } /* Release i2c bus */ @@ -1212,15 +1205,15 @@ static unsigned int poll(struct file *filep, poll_table *wait) struct lirc_buffer *rbuf = ir->l.rbuf; unsigned int ret; - dev_dbg(ir->l.dev, "poll called\n"); + dev_dbg(ir->l.dev, "%s called\n", __func__); rx = get_ir_rx(ir); - if (rx == NULL) { + if (!rx) { /* * Revisit this, if our poll function ever reports writeable * status for Tx */ - dev_dbg(ir->l.dev, "poll result = POLLERR\n"); + dev_dbg(ir->l.dev, "%s result = POLLERR\n", __func__); return POLLERR; } @@ -1231,9 +1224,9 @@ static unsigned int poll(struct file *filep, poll_table *wait) poll_wait(filep, &rbuf->wait_poll, wait); /* Indicate what ops could happen immediately without blocking */ - ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN|POLLRDNORM); + ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN | POLLRDNORM); - dev_dbg(ir->l.dev, "poll result = %s\n", + dev_dbg(ir->l.dev, "%s result = %s\n", __func__, ret ? "POLLIN|POLLRDNORM" : "none"); return ret; } @@ -1255,15 +1248,15 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) result = put_user(features, uptr); break; case LIRC_GET_REC_MODE: - if (!(features&LIRC_CAN_REC_MASK)) + if (!(features & LIRC_CAN_REC_MASK)) return -ENOSYS; result = put_user(LIRC_REC2MODE - (features&LIRC_CAN_REC_MASK), + (features & LIRC_CAN_REC_MASK), uptr); break; case LIRC_SET_REC_MODE: - if (!(features&LIRC_CAN_REC_MASK)) + if (!(features & LIRC_CAN_REC_MASK)) return -ENOSYS; result = get_user(mode, uptr); @@ -1271,13 +1264,13 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) result = -EINVAL; break; case LIRC_GET_SEND_MODE: - if (!(features&LIRC_CAN_SEND_MASK)) + if (!(features & LIRC_CAN_SEND_MASK)) return -ENOSYS; result = put_user(LIRC_MODE_PULSE, uptr); break; case LIRC_SET_SEND_MODE: - if (!(features&LIRC_CAN_SEND_MASK)) + if (!(features & LIRC_CAN_SEND_MASK)) return -ENOSYS; result = get_user(mode, uptr); @@ -1322,7 +1315,7 @@ static int open(struct inode *node, struct file *filep) /* find our IR struct */ ir = get_ir_device_by_minor(minor); - if (ir == NULL) + if (!ir) return -ENODEV; atomic_inc(&ir->open_count); @@ -1340,8 +1333,9 @@ static int close(struct inode *node, struct file *filep) /* find our IR struct */ struct IR *ir = filep->private_data; - if (ir == NULL) { - pr_err("ir: close: no private_data attached to the file!\n"); + if (!ir) { + pr_err("ir: %s: no private_data attached to the file!\n", + __func__); return -ENODEV; } @@ -1394,10 +1388,7 @@ static struct lirc_driver lirc_template = { .minor = -1, .code_length = 13, .buffer_size = BUFLEN / 2, - .sample_rate = 0, /* tell lirc_dev to not start its own kthread */ .chunk_size = 2, - .set_use_inc = set_use_inc, - .set_use_dec = set_use_dec, .fops = &lirc_fops, .owner = THIS_MODULE, }; @@ -1407,7 +1398,7 @@ static int ir_remove(struct i2c_client *client) if (strncmp("ir_tx_z8", client->name, 8) == 0) { struct IR_tx *tx = i2c_get_clientdata(client); - if (tx != NULL) { + if (tx) { mutex_lock(&tx->client_lock); tx->c = NULL; mutex_unlock(&tx->client_lock); @@ -1416,7 +1407,7 @@ static int ir_remove(struct i2c_client *client) } else if (strncmp("ir_rx_z8", client->name, 8) == 0) { struct IR_rx *rx = i2c_get_clientdata(client); - if (rx != NULL) { + if (rx) { mutex_lock(&rx->client_lock); rx->c = NULL; mutex_unlock(&rx->client_lock); @@ -1426,7 +1417,6 @@ static int ir_remove(struct i2c_client *client) return 0; } - /* ir_devices_lock must be held */ static struct IR *get_ir_device_by_adapter(struct i2c_adapter *adapter) { @@ -1467,14 +1457,14 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) return -ENXIO; pr_info("probing IR %s on %s (i2c-%d)\n", - tx_probe ? "Tx" : "Rx", adap->name, adap->nr); + tx_probe ? "Tx" : "Rx", adap->name, adap->nr); mutex_lock(&ir_devices_lock); /* Use a single struct IR instance for both the Rx and Tx functions */ ir = get_ir_device_by_adapter(adap); - if (ir == NULL) { - ir = kzalloc(sizeof(struct IR), GFP_KERNEL); + if (!ir) { + ir = kzalloc(sizeof(*ir), GFP_KERNEL); if (!ir) { ret = -ENOMEM; goto out_no_ir; @@ -1514,7 +1504,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) rx = get_ir_rx(ir); /* Set up a struct IR_tx instance */ - tx = kzalloc(sizeof(struct IR_tx), GFP_KERNEL); + tx = kzalloc(sizeof(*tx), GFP_KERNEL); if (!tx) { ret = -ENOMEM; goto out_put_xx; @@ -1547,7 +1537,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) fw_load(tx); /* Proceed only if the Rx client is also ready or not needed */ - if (rx == NULL && !tx_only) { + if (!rx && !tx_only) { dev_info(tx->ir->l.dev, "probe of IR Tx on %s (i2c-%d) done. Waiting on IR Rx.\n", adap->name, adap->nr); @@ -1558,7 +1548,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) tx = get_ir_tx(ir); /* Set up a struct IR_rx instance */ - rx = kzalloc(sizeof(struct IR_rx), GFP_KERNEL); + rx = kzalloc(sizeof(*rx), GFP_KERNEL); if (!rx) { ret = -ENOMEM; goto out_put_xx; @@ -1601,20 +1591,19 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) } /* Proceed only if the Tx client is also ready */ - if (tx == NULL) { + if (!tx) { pr_info("probe of IR Rx on %s (i2c-%d) done. Waiting on IR Tx.\n", - adap->name, adap->nr); + adap->name, adap->nr); goto out_ok; } } /* register with lirc */ - ir->l.minor = minor; /* module option: user requested minor number */ ir->l.minor = lirc_register_driver(&ir->l); - if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) { + if (ir->l.minor < 0) { dev_err(tx->ir->l.dev, - "%s: \"minor\" must be between 0 and %d (%d)!\n", - __func__, MAX_IRCTL_DEVICES-1, ir->l.minor); + "%s: lirc_register_driver() failed: %i\n", + __func__, ir->l.minor); ret = -EBADRQC; goto out_put_xx; } @@ -1623,9 +1612,9 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) adap->name, adap->nr, ir->l.minor); out_ok: - if (rx != NULL) + if (rx) put_ir_rx(rx, true); - if (tx != NULL) + if (tx) put_ir_tx(tx, true); put_ir_device(ir, true); dev_info(ir->l.dev, @@ -1635,10 +1624,10 @@ out_ok: return 0; out_put_xx: - if (rx != NULL) + if (rx) put_ir_rx(rx, true); out_put_tx: - if (tx != NULL) + if (tx) put_ir_tx(tx, true); out_put_ir: put_ir_device(ir, true); @@ -1686,9 +1675,6 @@ MODULE_LICENSE("GPL"); /* for compat with old name, which isn't all that accurate anymore */ MODULE_ALIAS("lirc_pvr150"); -module_param(minor, int, 0444); -MODULE_PARM_DESC(minor, "Preferred minor device number"); - module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Enable debugging messages"); diff --git a/include/media/cec-notifier.h b/include/media/cec-notifier.h index 413335c8cb52..298f996969df 100644 --- a/include/media/cec-notifier.h +++ b/include/media/cec-notifier.h @@ -106,6 +106,16 @@ static inline void cec_notifier_set_phys_addr_from_edid(struct cec_notifier *n, { } +static inline void cec_notifier_register(struct cec_notifier *n, + struct cec_adapter *adap, + void (*callback)(struct cec_adapter *adap, u16 pa)) +{ +} + +static inline void cec_notifier_unregister(struct cec_notifier *n) +{ +} + #endif #endif diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index cec7d35602d1..86d15a9b6c01 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -12,8 +12,6 @@ #define MAX_IRCTL_DEVICES 8 #define BUFLEN 16 -#define mod(n, div) ((n) % (div)) - #include <linux/slab.h> #include <linux/fs.h> #include <linux/ioctl.h> @@ -90,11 +88,6 @@ static inline int lirc_buffer_empty(struct lirc_buffer *buf) return !lirc_buffer_len(buf); } -static inline int lirc_buffer_available(struct lirc_buffer *buf) -{ - return buf->size - (lirc_buffer_len(buf) / buf->chunk_size); -} - static inline unsigned int lirc_buffer_read(struct lirc_buffer *buf, unsigned char *dest) { @@ -133,12 +126,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, * @buffer_size: Number of FIFO buffers with @chunk_size size. If zero, * creates a buffer with BUFLEN size (16 bytes). * - * @sample_rate: if zero, the device will wait for an event with a new - * code to be parsed. Otherwise, specifies the sample - * rate for polling. Value should be between 0 - * and HZ. If equal to HZ, it would mean one polling per - * second. - * * @features: lirc compatible hardware features, like LIRC_MODE_RAW, * LIRC_CAN\_\*, as defined at include/media/lirc.h. * @@ -153,22 +140,10 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, * @max_timeout: Maximum timeout for record. Valid only if * LIRC_CAN_SET_REC_TIMEOUT is defined. * - * @add_to_buf: add_to_buf will be called after specified period of the - * time or triggered by the external event, this behavior - * depends on value of the sample_rate this function will - * be called in user context. This routine should return - * 0 if data was added to the buffer and -ENODATA if none - * was available. This should add some number of bits - * evenly divisible by code_length to the buffer. - * * @rbuf: if not NULL, it will be used as a read buffer, you will * have to write to the buffer by other means, like irq's * (see also lirc_serial.c). * - * @set_use_inc: set_use_inc will be called after device is opened - * - * @set_use_dec: set_use_dec will be called after device is closed - * * @rdev: Pointed to struct rc_dev associated with the LIRC * device. * @@ -188,7 +163,6 @@ struct lirc_driver { int minor; __u32 code_length; unsigned int buffer_size; /* in chunks holding one code each */ - int sample_rate; __u32 features; unsigned int chunk_size; @@ -196,10 +170,7 @@ struct lirc_driver { void *data; int min_timeout; int max_timeout; - int (*add_to_buf)(void *data, struct lirc_buffer *buf); struct lirc_buffer *rbuf; - int (*set_use_inc)(void *data); - void (*set_use_dec)(void *data); struct rc_dev *rdev; const struct file_operations *fops; struct device *dev; @@ -232,7 +203,4 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait); long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg); ssize_t lirc_dev_fop_read(struct file *file, char __user *buffer, size_t length, loff_t *ppos); -ssize_t lirc_dev_fop_write(struct file *file, const char __user *buffer, - size_t length, loff_t *ppos); - #endif diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 8e2a236a4d03..c69d8c8a66d0 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -31,7 +31,7 @@ struct v4l2_async_notifier; * v4l2_async_subdev.match ops * @V4L2_ASYNC_MATCH_DEVNAME: Match will use the device name * @V4L2_ASYNC_MATCH_I2C: Match will check for I2C adapter ID and address - * @V4L2_ASYNC_MATCH_OF: Match will use OF node + * @V4L2_ASYNC_MATCH_FWNODE: Match will use firmware node * * This enum is used by the asyncrhronous sub-device logic to define the * algorithm that will be used to match an asynchronous device. @@ -40,7 +40,7 @@ enum v4l2_async_match_type { V4L2_ASYNC_MATCH_CUSTOM, V4L2_ASYNC_MATCH_DEVNAME, V4L2_ASYNC_MATCH_I2C, - V4L2_ASYNC_MATCH_OF, + V4L2_ASYNC_MATCH_FWNODE, }; /** @@ -55,8 +55,8 @@ struct v4l2_async_subdev { enum v4l2_async_match_type match_type; union { struct { - const struct device_node *node; - } of; + struct fwnode_handle *fwnode; + } fwnode; struct { const char *name; } device_name; diff --git a/include/media/v4l2-flash-led-class.h b/include/media/v4l2-flash-led-class.h index b0fe4d6f4a5f..f9dcd54c1745 100644 --- a/include/media/v4l2-flash-led-class.h +++ b/include/media/v4l2-flash-led-class.h @@ -108,7 +108,7 @@ static inline struct v4l2_flash *v4l2_ctrl_to_v4l2_flash(struct v4l2_ctrl *c) /** * v4l2_flash_init - initialize V4L2 flash led sub-device * @dev: flash device, e.g. an I2C device - * @of_node: of_node of the LED, may be NULL if the same as device's + * @fwn: fwnode_handle of the LED, may be NULL if the same as device's * @fled_cdev: LED flash class device to wrap * @iled_cdev: LED flash class device representing indicator LED associated * with fled_cdev, may be NULL @@ -122,7 +122,7 @@ static inline struct v4l2_flash *v4l2_ctrl_to_v4l2_flash(struct v4l2_ctrl *c) * PTR_ERR() to obtain the numeric return value. */ struct v4l2_flash *v4l2_flash_init( - struct device *dev, struct device_node *of_node, + struct device *dev, struct fwnode_handle *fwn, struct led_classdev_flash *fled_cdev, struct led_classdev_flash *iled_cdev, const struct v4l2_flash_ops *ops, @@ -138,7 +138,7 @@ void v4l2_flash_release(struct v4l2_flash *v4l2_flash); #else static inline struct v4l2_flash *v4l2_flash_init( - struct device *dev, struct device_node *of_node, + struct device *dev, struct fwnode_handle *fwn, struct led_classdev_flash *fled_cdev, struct led_classdev_flash *iled_cdev, const struct v4l2_flash_ops *ops, diff --git a/include/media/v4l2-of.h b/include/media/v4l2-fwnode.h index 4dc34b245d47..ecc1233a873e 100644 --- a/include/media/v4l2-of.h +++ b/include/media/v4l2-fwnode.h @@ -1,5 +1,8 @@ /* - * V4L2 OF binding parsing library + * V4L2 fwnode binding parsing library + * + * Copyright (c) 2016 Intel Corporation. + * Author: Sakari Ailus <sakari.ailus@linux.intel.com> * * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> @@ -11,20 +14,20 @@ * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. */ -#ifndef _V4L2_OF_H -#define _V4L2_OF_H +#ifndef _V4L2_FWNODE_H +#define _V4L2_FWNODE_H +#include <linux/errno.h> +#include <linux/fwnode.h> #include <linux/list.h> #include <linux/types.h> -#include <linux/errno.h> -#include <linux/of_graph.h> #include <media/v4l2-mediabus.h> -struct device_node; +struct fwnode_handle; /** - * struct v4l2_of_bus_mipi_csi2 - MIPI CSI-2 bus data structure + * struct v4l2_fwnode_bus_mipi_csi2 - MIPI CSI-2 bus data structure * @flags: media bus (V4L2_MBUS_*) flags * @data_lanes: an array of physical data lane indexes * @clock_lane: physical lane index of the clock lane @@ -32,7 +35,7 @@ struct device_node; * @lane_polarities: polarity of the lanes. The order is the same of * the physical lanes. */ -struct v4l2_of_bus_mipi_csi2 { +struct v4l2_fwnode_bus_mipi_csi2 { unsigned int flags; unsigned char data_lanes[4]; unsigned char clock_lane; @@ -41,88 +44,61 @@ struct v4l2_of_bus_mipi_csi2 { }; /** - * struct v4l2_of_bus_parallel - parallel data bus data structure + * struct v4l2_fwnode_bus_parallel - parallel data bus data structure * @flags: media bus (V4L2_MBUS_*) flags * @bus_width: bus width in bits * @data_shift: data shift in bits */ -struct v4l2_of_bus_parallel { +struct v4l2_fwnode_bus_parallel { unsigned int flags; unsigned char bus_width; unsigned char data_shift; }; /** - * struct v4l2_of_endpoint - the endpoint data structure - * @base: struct of_endpoint containing port, id, and local of_node + * struct v4l2_fwnode_endpoint - the endpoint data structure + * @base: fwnode endpoint of the v4l2_fwnode * @bus_type: bus type * @bus: bus configuration data structure * @link_frequencies: array of supported link frequencies * @nr_of_link_frequencies: number of elements in link_frequenccies array */ -struct v4l2_of_endpoint { - struct of_endpoint base; - /* Fields below this line will be zeroed by v4l2_of_parse_endpoint() */ +struct v4l2_fwnode_endpoint { + struct fwnode_endpoint base; + /* + * Fields below this line will be zeroed by + * v4l2_fwnode_parse_endpoint() + */ enum v4l2_mbus_type bus_type; union { - struct v4l2_of_bus_parallel parallel; - struct v4l2_of_bus_mipi_csi2 mipi_csi2; + struct v4l2_fwnode_bus_parallel parallel; + struct v4l2_fwnode_bus_mipi_csi2 mipi_csi2; } bus; u64 *link_frequencies; unsigned int nr_of_link_frequencies; }; /** - * struct v4l2_of_link - a link between two endpoints + * struct v4l2_fwnode_link - a link between two endpoints * @local_node: pointer to device_node of this endpoint * @local_port: identifier of the port this endpoint belongs to * @remote_node: pointer to device_node of the remote endpoint * @remote_port: identifier of the port the remote endpoint belongs to */ -struct v4l2_of_link { - struct device_node *local_node; +struct v4l2_fwnode_link { + struct fwnode_handle *local_node; unsigned int local_port; - struct device_node *remote_node; + struct fwnode_handle *remote_node; unsigned int remote_port; }; -#ifdef CONFIG_OF -int v4l2_of_parse_endpoint(const struct device_node *node, - struct v4l2_of_endpoint *endpoint); -struct v4l2_of_endpoint *v4l2_of_alloc_parse_endpoint( - const struct device_node *node); -void v4l2_of_free_endpoint(struct v4l2_of_endpoint *endpoint); -int v4l2_of_parse_link(const struct device_node *node, - struct v4l2_of_link *link); -void v4l2_of_put_link(struct v4l2_of_link *link); -#else /* CONFIG_OF */ - -static inline int v4l2_of_parse_endpoint(const struct device_node *node, - struct v4l2_of_endpoint *link) -{ - return -ENOSYS; -} - -static inline struct v4l2_of_endpoint *v4l2_of_alloc_parse_endpoint( - const struct device_node *node) -{ - return NULL; -} - -static inline void v4l2_of_free_endpoint(struct v4l2_of_endpoint *endpoint) -{ -} - -static inline int v4l2_of_parse_link(const struct device_node *node, - struct v4l2_of_link *link) -{ - return -ENOSYS; -} - -static inline void v4l2_of_put_link(struct v4l2_of_link *link) -{ -} - -#endif /* CONFIG_OF */ +int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode, + struct v4l2_fwnode_endpoint *vep); +struct v4l2_fwnode_endpoint *v4l2_fwnode_endpoint_alloc_parse( + struct fwnode_handle *fwnode); +void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep); +int v4l2_fwnode_parse_link(struct fwnode_handle *fwnode, + struct v4l2_fwnode_link *link); +void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link); -#endif /* _V4L2_OF_H */ +#endif /* _V4L2_FWNODE_H */ diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 0ab1c5df6fac..a40760174797 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -787,7 +787,8 @@ struct v4l2_subdev_platform_data { * is attached. * @devnode: subdev device node * @dev: pointer to the physical device, if any - * @of_node: The device_node of the subdev, usually the same as dev->of_node. + * @fwnode: The fwnode_handle of the subdev, usually the same as + * either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL). * @async_list: Links this subdev to a global subdev_list or @notifier->done * list. * @asd: Pointer to respective &struct v4l2_async_subdev. @@ -818,7 +819,7 @@ struct v4l2_subdev { void *host_priv; struct video_device *devnode; struct device *dev; - struct device_node *of_node; + struct fwnode_handle *fwnode; struct list_head async_list; struct v4l2_async_subdev *asd; struct v4l2_async_notifier *notifier; |