From 333a6515344f5dc4ed0772b8fe252a2246f2e099 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Jan 2016 07:29:13 -0200 Subject: Revert "[media] Postpone the addition of MEDIA_IOC_G_TOPOLOGY" Enable MEDIA_IOC_G_TOPOLOGY ioctl for Kernel 4.6. This reverts commit be0270ec89e6b9b49de7e533dd1f3a89ad34d205. Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/media.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 1e3c8cb43bd7..5dbb208e5451 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -286,7 +286,7 @@ struct media_links_enum { * later, before the adding this API upstream. */ -#if 0 /* Let's postpone it to Kernel 4.6 */ + struct media_v2_entity { __u32 id; char name[64]; /* FIXME: move to a property? (RFC says so) */ @@ -351,7 +351,6 @@ static inline void __user *media_get_uptr(__u64 arg) { return (void __user *)(uintptr_t)arg; } -#endif /* ioctls */ @@ -359,9 +358,6 @@ static inline void __user *media_get_uptr(__u64 arg) #define MEDIA_IOC_ENUM_ENTITIES _IOWR('|', 0x01, struct media_entity_desc) #define MEDIA_IOC_ENUM_LINKS _IOWR('|', 0x02, struct media_links_enum) #define MEDIA_IOC_SETUP_LINK _IOWR('|', 0x03, struct media_link_desc) - -#if 0 /* Let's postpone it to Kernel 4.6 */ #define MEDIA_IOC_G_TOPOLOGY _IOWR('|', 0x04, struct media_v2_topology) -#endif #endif /* __LINUX_MEDIA_H */ -- cgit v1.2.3 From 163c9bca101caf000691b56fb3834905e62cbba3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 08:39:33 -0200 Subject: [media] tuner.h: rename TUNER_PAD_IF_OUTPUT to TUNER_PAD_OUTPUT The output of a tuner is not only IF frequencies. They may also output audio on some of its pins, and may even be a zero-IF tuner, with outputs a baseband. So, rename the PAD name to make it clearer and add a proper documentation about that at tuner.h. No functional changes. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 2 +- drivers/media/usb/au0828/au0828-core.c | 2 +- drivers/media/usb/cx231xx/cx231xx-cards.c | 2 +- drivers/media/usb/dvb-usb-v2/mxl111sf.c | 2 +- drivers/media/v4l2-core/tuner-core.c | 2 +- include/media/tuner.h | 21 ++++++++++++++++++--- 6 files changed, 23 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 560450a0b32a..a7de62ebc415 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -661,7 +661,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, if (ntuner && ndemod) { ret = media_create_pad_links(mdev, MEDIA_ENT_F_TUNER, - tuner, TUNER_PAD_IF_OUTPUT, + tuner, TUNER_PAD_OUTPUT, MEDIA_ENT_F_DTV_DEMOD, demod, 0, MEDIA_LNK_FL_ENABLED, false); diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index 9e29e70a78d7..df2bc3f732b6 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -276,7 +276,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev) return -EINVAL; if (tuner) { - ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT, + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, decoder, 0, MEDIA_LNK_FL_ENABLED); if (ret) diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 620b83d03f75..54e43fe13e6d 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1259,7 +1259,7 @@ static int cx231xx_create_media_graph(struct cx231xx *dev) return 0; if (tuner) { - ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT, decoder, 0, + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, decoder, 0, MEDIA_LNK_FL_ENABLED); if (ret < 0) return ret; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index b669deccc34c..e7978e4e40ea 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -888,7 +888,7 @@ static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap) state->tuner.function = MEDIA_ENT_F_TUNER; state->tuner.name = "mxl111sf tuner"; state->tuner_pads[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; - state->tuner_pads[TUNER_PAD_IF_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + state->tuner_pads[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&state->tuner, TUNER_NUM_PADS, state->tuner_pads); diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index 76496fd282aa..a1f858b34187 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -697,7 +697,7 @@ static int tuner_probe(struct i2c_client *client, register_client: #if defined(CONFIG_MEDIA_CONTROLLER) t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; - t->pad[TUNER_PAD_IF_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; t->sd.entity.function = MEDIA_ENT_F_TUNER; t->sd.entity.name = t->name; diff --git a/include/media/tuner.h b/include/media/tuner.h index e5321fda5489..c5994fe865a0 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -21,11 +21,26 @@ #include -/* Tuner PADs */ -/* FIXME: is this the right place for it? */ +/** + * enum tuner_pad_index - tuner pad index + * + * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a + * RF connector entity. + * @TUNER_PAD_OUTPUT: Tuner output pad. This is actually more complex than + * a single pad output, as, in addition to luminance and + * chrominance IF a tuner may have internally an + * audio decoder (like xc3028) or it may produce an audio + * IF that will be used by an audio decoder like msp34xx. + * It may also have an IF-PLL demodulator on it, like + * tuners with tda9887. Yet, currently, we don't need to + * represent all the dirty details, as this is transparent + * for the V4L2 API usage. So, let's represent all kinds + * of different outputs as a single source pad. + * @TUNER_NUM_PADS: Number of pads of the tuner. + */ enum tuner_pad_index { TUNER_PAD_RF_INPUT, - TUNER_PAD_IF_OUTPUT, + TUNER_PAD_OUTPUT, TUNER_NUM_PADS }; -- cgit v1.2.3 From 6aad127d37b609ca40ee3b93454a58ee6ed5a1ce Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 06:11:30 -0200 Subject: [media] v4l2-mc.h: move tuner PAD definitions to this new header The customer PC hardware can be shipped with lots of different configurations, as vendors use to replace some of the chips on their hardware along the time. All drivers that support such devices are prepared to handle the hardware differences, using their own auto-probing logic. They do it in a way that number of inputs and outputs for a given hardware type doesn't change. Now that we're adding media controller capabilities to those drivers, we need to standardize the number of inputs and outputs for each hardware type, as we want to have a generic function at the V4L2 core that would create the links for the entities that are expected on such hardware. Such standard is already there for tuners, but tuner.h is not the best place to store such data, as we'll need to add definitions also for analog TV demodulators. Also, we'll need a place to put a set of MC handling functions. So, let's create a v4l2-mc.h to store such kind of definitions. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/device-drivers.tmpl | 1 + include/media/tuner.h | 24 +------------------ include/media/v4l2-mc.h | 38 +++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 23 deletions(-) create mode 100644 include/media/v4l2-mc.h (limited to 'include') diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index cdd8b24db68d..cc303a2f641c 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -229,6 +229,7 @@ X!Isound/sound_firmware.c !Iinclude/media/v4l2-dv-timings.h !Iinclude/media/v4l2-event.h !Iinclude/media/v4l2-flash-led-class.h +!Iinclude/media/v4l2-mc.h !Iinclude/media/v4l2-mediabus.h !Iinclude/media/v4l2-mem2mem.h !Iinclude/media/v4l2-of.h diff --git a/include/media/tuner.h b/include/media/tuner.h index c5994fe865a0..b3edc14e763f 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -20,29 +20,7 @@ #ifdef __KERNEL__ #include - -/** - * enum tuner_pad_index - tuner pad index - * - * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a - * RF connector entity. - * @TUNER_PAD_OUTPUT: Tuner output pad. This is actually more complex than - * a single pad output, as, in addition to luminance and - * chrominance IF a tuner may have internally an - * audio decoder (like xc3028) or it may produce an audio - * IF that will be used by an audio decoder like msp34xx. - * It may also have an IF-PLL demodulator on it, like - * tuners with tda9887. Yet, currently, we don't need to - * represent all the dirty details, as this is transparent - * for the V4L2 API usage. So, let's represent all kinds - * of different outputs as a single source pad. - * @TUNER_NUM_PADS: Number of pads of the tuner. - */ -enum tuner_pad_index { - TUNER_PAD_RF_INPUT, - TUNER_PAD_OUTPUT, - TUNER_NUM_PADS -}; +#include #define ADDR_UNSET (255) diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h new file mode 100644 index 000000000000..f6fcd70f3548 --- /dev/null +++ b/include/media/v4l2-mc.h @@ -0,0 +1,38 @@ +/* + * v4l2-mc.h - Media Controller V4L2 types and prototypes + * + * Copyright (C) 2016 Mauro Carvalho Chehab + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/** + * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER + * + * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a + * RF connector entity. + * @TUNER_PAD_OUTPUT: Tuner output pad. This is actually more complex than + * a single pad output, as, in addition to luminance and + * chrominance IF a tuner may have internally an + * audio decoder (like xc3028) or it may produce an audio + * IF that will be used by an audio decoder like msp34xx. + * It may also have an IF-PLL demodulator on it, like + * tuners with tda9887. Yet, currently, we don't need to + * represent all the dirty details, as this is transparent + * for the V4L2 API usage. So, let's represent all kinds + * of different outputs as a single source pad. + * @TUNER_NUM_PADS: Number of pads of the tuner. + */ +enum tuner_pad_index { + TUNER_PAD_RF_INPUT, + TUNER_PAD_OUTPUT, + TUNER_NUM_PADS +}; \ No newline at end of file -- cgit v1.2.3 From 5c9077eabc9a0ffbd4c8b0724ddcd69ef2b1a7ed Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 07:00:08 -0200 Subject: [media] v4l2-mc.h: Split audio from baseband output Analog TV tuners have a separate output pad for the audio IF or audio sampled data. This pad is connected to a different chipset. Add an extra pad for it and improve the documentation. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/tuner-core.c | 1 + include/media/v4l2-mc.h | 28 +++++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index a1f858b34187..d6bd9ce1101d 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -698,6 +698,7 @@ register_client: #if defined(CONFIG_MEDIA_CONTROLLER) t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; t->sd.entity.function = MEDIA_ENT_F_TUNER; t->sd.entity.name = t->name; diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index f6fcd70f3548..c174e5b4f188 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -19,20 +19,26 @@ * * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a * RF connector entity. - * @TUNER_PAD_OUTPUT: Tuner output pad. This is actually more complex than - * a single pad output, as, in addition to luminance and - * chrominance IF a tuner may have internally an - * audio decoder (like xc3028) or it may produce an audio - * IF that will be used by an audio decoder like msp34xx. - * It may also have an IF-PLL demodulator on it, like - * tuners with tda9887. Yet, currently, we don't need to - * represent all the dirty details, as this is transparent - * for the V4L2 API usage. So, let's represent all kinds - * of different outputs as a single source pad. + * @TUNER_PAD_OUTPUT: Tuner video output source pad. Contains the video + * chrominance and luminance or the hole bandwidth + * of the signal converted to an Intermediate Frequency + * (IF) or to baseband (on zero-IF tuners). + * @TUNER_PAD_AUD_OUT: Tuner audio output source pad. Tuners used to decode + * analog TV signals have an extra pad for audio output. + * Old tuners use an analog stage with a saw filter for + * the audio IF frequency. The output of the pad is, in + * this case, the audio IF, with should be decoded either + * by the bridge chipset (that's the case of cx2388x + * chipsets) or may require an external IF sound + * processor, like msp34xx. On modern silicon tuners, + * the audio IF decoder is usually incorporated at the + * tuner. On such case, the output of this pad is an + * audio sampled data. * @TUNER_NUM_PADS: Number of pads of the tuner. */ enum tuner_pad_index { TUNER_PAD_RF_INPUT, TUNER_PAD_OUTPUT, + TUNER_PAD_AUD_OUT, TUNER_NUM_PADS -}; \ No newline at end of file +}; -- cgit v1.2.3 From 06131932c1d5f1bd09832f42be658906a27749fb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 28 Jan 2016 07:28:08 -0200 Subject: [media] media.h: add support for IF-PLL video/sound decoder Very old hardware may have an analog stage tuner. Those hardware consists of a PLL that converts a RF signal into IF signals. Depending on the hardware, those video IF signal can be decoded directly by the bridge chipset. Most Conexant chips (bt8x8, cx2388x, etc) have internally the decoders for that. Yet, even on such hardware, the tuner may have internally its own TV multi-standard decoder like tda9887. The same happens with the audio IF signal, where some bridges are capable of receiving it, while others require an external IF-PLL sound decoder, like msp3400. Those external IF-PLL audio and video decoders have their own I2C address, and use different drivers to handle them. So, they're mapped as different subdevices on Linux. Thankfully, all modern hardware comes with an IC chip that has both the RF and the IF stages on it, being capable of decoding audio and video IF signals internally. Yet, as we need to support drivers that can work with either analog or silicon tuners, we need to add two entity types for those old hardware. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/media-types.xml | 29 ++++++++++++++++++++++++- include/uapi/linux/media.h | 17 +++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/Documentation/DocBook/media/v4l/media-types.xml b/Documentation/DocBook/media/v4l/media-types.xml index 1af384250910..751c3d027103 100644 --- a/Documentation/DocBook/media/v4l/media-types.xml +++ b/Documentation/DocBook/media/v4l/media-types.xml @@ -84,7 +84,34 @@ MEDIA_ENT_F_TUNER - Digital TV, analog TV, radio and/or software radio tuner. + Digital TV, analog TV, radio and/or software radio tuner, + with consists on a PLL tuning stage that converts radio + frequency (RF) signal into an Intermediate Frequency (IF). + Modern tuners have internally IF-PLL decoders for audio + and video, but older models have those stages implemented + on separate entities. + + + + MEDIA_ENT_F_IF_VID_DECODER + IF-PLL video decoder. It receives the IF from a PLL + and decodes the analog TV video signal. This is commonly + found on some very old analog tuners, like Philips MK3 + designs. They all contain a tda9887 (or some software + compatible similar chip, like tda9885). Those devices + use a different I2C address than the tuner PLL. + + + + MEDIA_ENT_F_IF_AUD_DECODER + IF-PLL sound decoder. It receives the IF from a PLL + and decodes the analog TV audio signal. This is commonly + found on some very old analog hardware, like Micronas + msp3400, Philips tda9840, tda985x, etc. Those devices + use a different I2C address than the tuner PLL and + should be controlled together with the IF-PLL video + decoder. + diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 5dbb208e5451..c9eb42a6c021 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -88,6 +88,15 @@ struct media_device_info { #define MEDIA_ENT_F_IO_VBI (MEDIA_ENT_F_BASE + 32) #define MEDIA_ENT_F_IO_SWRADIO (MEDIA_ENT_F_BASE + 33) +/* + * Analog TV IF-PLL decoders + * + * It is a responsibility of the master/bridge drivers to create links + * for MEDIA_ENT_F_IF_VID_DECODER and MEDIA_ENT_F_IF_AUD_DECODER. + */ +#define MEDIA_ENT_F_IF_VID_DECODER (MEDIA_ENT_F_BASE + 41) +#define MEDIA_ENT_F_IF_AUD_DECODER (MEDIA_ENT_F_BASE + 42) + /* * Don't touch on those. The ranges MEDIA_ENT_F_OLD_BASE and * MEDIA_ENT_F_OLD_SUBDEV_BASE are kept to keep backward compatibility @@ -107,8 +116,12 @@ struct media_device_info { #define MEDIA_ENT_F_LENS (MEDIA_ENT_F_OLD_SUBDEV_BASE + 3) #define MEDIA_ENT_F_ATV_DECODER (MEDIA_ENT_F_OLD_SUBDEV_BASE + 4) /* - * It is a responsibility of the entity drivers to add connectors and links - * for the tuner entities. + * It is a responsibility of the master/bridge drivers to add connectors + * and links for MEDIA_ENT_F_TUNER. Please notice that some old tuners + * may require the usage of separate I2C chips to decode analog TV signals, + * when the master/bridge chipset doesn't have its own TV standard decoder. + * On such cases, the IF-PLL staging is mapped via one or two entities: + * MEDIA_ENT_F_IF_VID_DECODER and/or MEDIA_ENT_F_IF_AUD_DECODER. */ #define MEDIA_ENT_F_TUNER (MEDIA_ENT_F_OLD_SUBDEV_BASE + 5) -- cgit v1.2.3 From 953a457e50958494cfa90b41a13c26e9fb04195c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 07:00:37 -0200 Subject: [media] v4l2-mc.h Add pads for audio and video IF-PLL decoders The audio and video IF-PLL decoders have one sink and one source PAD. Add macro names for those pads and describe what kind of signals are represented at such pads. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/tuner-core.c | 27 +++++++++++++++++++++------ include/media/v4l2-mc.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index d6bd9ce1101d..731487be5baa 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -696,17 +696,32 @@ static int tuner_probe(struct i2c_client *client, /* Should be just before return */ register_client: #if defined(CONFIG_MEDIA_CONTROLLER) - t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; - t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; - t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; - t->sd.entity.function = MEDIA_ENT_F_TUNER; t->sd.entity.name = t->name; + /* + * Handle the special case where the tuner has actually + * two stages: the PLL to tune into a frequency and the + * IF-PLL demodulator (tda988x). + */ + if (t->type == TUNER_TDA9887) { + t->pad[IF_VID_DEC_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + t->pad[IF_VID_DEC_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&t->sd.entity, + IF_VID_DEC_PAD_NUM_PADS, + &t->pad[0]); + t->sd.entity.function = MEDIA_ENT_F_IF_VID_DECODER; + } else { + t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; + t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&t->sd.entity, TUNER_NUM_PADS, + &t->pad[0]); + t->sd.entity.function = MEDIA_ENT_F_TUNER; + } - ret = media_entity_pads_init(&t->sd.entity, TUNER_NUM_PADS, &t->pad[0]); if (ret < 0) { tuner_err("failed to initialize media entity!\n"); kfree(t); - return -ENODEV; + return ret; } #endif /* Sets a default mode */ diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index c174e5b4f188..6a6ef5bc767e 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -42,3 +42,35 @@ enum tuner_pad_index { TUNER_PAD_AUD_OUT, TUNER_NUM_PADS }; + +/** + * enum if_vid_dec_index - video IF-PLL pad index for + * MEDIA_ENT_F_IF_VID_DECODER + * + * @IF_VID_DEC_PAD_IF_INPUT: video Intermediate Frequency (IF) sink pad + * @IF_VID_DEC_PAD_OUT: IF-PLL video output source pad. Contains the + * video chrominance and luminance IF signals. + * @IF_VID_DEC_PAD_NUM_PADS: Number of pads of the video IF-PLL. + */ +enum if_vid_dec_pad_index { + IF_VID_DEC_PAD_IF_INPUT, + IF_VID_DEC_PAD_OUT, + IF_VID_DEC_PAD_NUM_PADS +}; + +/** + * enum if_aud_dec_index - audio/sound IF-PLL pad index for + * MEDIA_ENT_F_IF_AUD_DECODER + * + * @IF_AUD_DEC_PAD_IF_INPUT: audio Intermediate Frequency (IF) sink pad + * @IF_AUD_DEC_PAD_OUT: IF-PLL audio output source pad. Contains the + * audio sampled stream data, usually connected + * to the bridge bus via an Inter-IC Sound (I2S) + * bus. + * @IF_AUD_DEC_PAD_NUM_PADS: Number of pads of the audio IF-PLL. + */ +enum if_aud_dec_pad_index { + IF_AUD_DEC_PAD_IF_INPUT, + IF_AUD_DEC_PAD_OUT, + IF_AUD_DEC_PAD_NUM_PADS +}; -- cgit v1.2.3 From e4001e955bec5566848624635cfb2d353ebac507 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 07:00:57 -0200 Subject: [media] v4l2-mc: add analog TV demodulator pad index macros We also need to standardize the PAD index macros for demods, as they all should look the same in a media graph. Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-mc.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'include') diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 6a6ef5bc767e..df115195690e 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -74,3 +74,18 @@ enum if_aud_dec_pad_index { IF_AUD_DEC_PAD_OUT, IF_AUD_DEC_PAD_NUM_PADS }; + +/** + * enum demod_pad_index - analog TV pad index for MEDIA_ENT_F_ATV_DECODER + * + * @DEMOD_PAD_IF_INPUT: IF input sink pad. + * @DEMOD_PAD_VID_OUT: Video output source pad. + * @DEMOD_PAD_VBI_OUT: Vertical Blank Interface (VBI) output source pad. + * @DEMOD_NUM_PADS: Maximum number of output pads. + */ +enum demod_pad_index { + DEMOD_PAD_IF_INPUT, + DEMOD_PAD_VID_OUT, + DEMOD_PAD_VBI_OUT, + DEMOD_NUM_PADS +}; -- cgit v1.2.3 From 80100fd9ebb9f2414892a1178d26a4253e6c0bcf Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 11 Jan 2016 11:21:15 -0200 Subject: [media] media: v4l: Dual license v4l2-common.h under GPL v2 and BSD licenses The v4l2-common.h user space header was split off from videodev2.h, but the dual licensing of the videodev2.h (as well as other V4L2 headers) was missed. Change the license of the v4l2-common.h from GNU GPL v2 to both GNU GPL v2 and BSD. Sakari Ailus : > Would you approve a license change of the patches to > include/uapi/linux/v4l2-common.h (formerly include/linux/v4l2-common.h) you > or your company have contributed from GNU GPL v2 to dual GNU GPL v2 and BSD > licenses, changing the copyright notice in the file as below (from > videodev2.h): > > -------------8<------------ > * 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 > * the Free Software Foundation; either version 2 of the License, or > * (at your option) any later version. > * > * This program is distributed in the hope that it will be useful, > * but WITHOUT ANY WARRANTY; without even the implied warranty of > * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > * GNU General Public License for more details. > * > * Alternatively you can redistribute this file under the terms of the > * BSD license as stated below: > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions > * are met: > * 1. Redistributions of source code must retain the above copyright > * notice, this list of conditions and the following disclaimer. > * 2. Redistributions in binary form must reproduce the above copyright > * notice, this list of conditions and the following disclaimer in > * the documentation and/or other materials provided with the > * distribution. > * 3. The names of its contributors may not be used to endorse or promote > * products derived from this software without specific prior written > * permission. > * > * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED > * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR > * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF > * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS > * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > -------------8<------------ Mauro Carvalho Chehab : > No problem from my side. Hans Verkuil : > Acked-by: Hans Verkuil Aaro Koskinen : > This fine also for us. > > Acked-by: Aaro Koskinen Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Acked-by: Aaro Koskinen Acked-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/v4l2-common.h | 46 ++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/v4l2-common.h b/include/uapi/linux/v4l2-common.h index 15273987093e..5b3f685a2d50 100644 --- a/include/uapi/linux/v4l2-common.h +++ b/include/uapi/linux/v4l2-common.h @@ -10,19 +10,43 @@ * Copyright (C) 2012 Nokia Corporation * Contact: Sakari Ailus * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA + * Alternatively you can redistribute this file under the terms of the + * BSD license as stated below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. The names of its contributors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -- cgit v1.2.3 From 54d0dbac1266d2b9a6b5a87316162a068ad545bf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 07:02:43 -0200 Subject: [media] v4l2-mc: add a generic function to create the media graph The em28xx_v4l2_create_media_graph() is almost generic enough to be at the core, as an ancillary function. Make it even more generic, by getting rid of em28xx-specific code, relying only at the media_device, in order to discover all entities found on PC-customer's hardware and add it at the V4L2 core. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/Makefile | 1 + drivers/media/v4l2-core/v4l2-mc.c | 186 ++++++++++++++++++++++++++++++++++++++ include/media/v4l2-mc.h | 25 +++++ 3 files changed, 212 insertions(+) create mode 100644 drivers/media/v4l2-core/v4l2-mc.c (limited to 'include') diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile index 1dc8bba2b198..795a5352761d 100644 --- a/drivers/media/v4l2-core/Makefile +++ b/drivers/media/v4l2-core/Makefile @@ -16,6 +16,7 @@ endif ifeq ($(CONFIG_TRACEPOINTS),y) videodev-objs += vb2-trace.o v4l2-trace.o endif +videodev-$(CONFIG_MEDIA_CONTROLLER) += v4l2-mc.o obj-$(CONFIG_VIDEO_V4L2) += videodev.o obj-$(CONFIG_VIDEO_V4L2) += v4l2-common.o diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c new file mode 100644 index 000000000000..e6d2a711bb0b --- /dev/null +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -0,0 +1,186 @@ +/* + * Media Controller ancillary functions + * + * (c) 2016 Mauro Carvalho Chehab + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +int v4l2_mc_create_media_graph(struct media_device *mdev) + +{ + struct media_entity *entity; + struct media_entity *if_vid = NULL, *if_aud = NULL, *sensor = NULL; + struct media_entity *tuner = NULL, *decoder = NULL; + struct media_entity *io_v4l = NULL, *io_vbi = NULL, *io_swradio = NULL; + bool is_webcam = false; + u32 flags; + int ret; + + if (!mdev) + return 0; + + media_device_for_each_entity(entity, mdev) { + switch (entity->function) { + case MEDIA_ENT_F_IF_VID_DECODER: + if_vid = entity; + break; + case MEDIA_ENT_F_IF_AUD_DECODER: + if_aud = entity; + break; + case MEDIA_ENT_F_TUNER: + tuner = entity; + break; + case MEDIA_ENT_F_ATV_DECODER: + decoder = entity; + break; + case MEDIA_ENT_F_IO_V4L: + io_v4l = entity; + break; + case MEDIA_ENT_F_IO_VBI: + io_vbi = entity; + break; + case MEDIA_ENT_F_IO_SWRADIO: + io_swradio = entity; + break; + case MEDIA_ENT_F_CAM_SENSOR: + sensor = entity; + is_webcam = true; + break; + } + } + + /* It should have at least one I/O entity */ + if (!io_v4l && !io_vbi && !io_swradio) + return -EINVAL; + + /* + * Here, webcams are modelled on a very simple way: the sensor is + * connected directly to the I/O entity. All dirty details, like + * scaler and crop HW are hidden. While such mapping is not enough + * for mc-centric hardware, it is enough for v4l2 interface centric + * PC-consumer's hardware. + */ + if (is_webcam) { + if (!io_v4l) + return -EINVAL; + + media_device_for_each_entity(entity, mdev) { + if (entity->function != MEDIA_ENT_F_CAM_SENSOR) + continue; + ret = media_create_pad_link(entity, 0, + io_v4l, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + if (!decoder) + return 0; + } + + /* The device isn't a webcam. So, it should have a decoder */ + if (!decoder) + return -EINVAL; + + /* Link the tuner and IF video output pads */ + if (tuner) { + if (if_vid) { + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, + if_vid, + IF_VID_DEC_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT, + decoder, DEMOD_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } else { + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, + decoder, DEMOD_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + if (if_aud) { + ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT, + if_aud, + IF_AUD_DEC_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } else { + if_aud = tuner; + } + + } + + /* Create demod to V4L, VBI and SDR radio links */ + if (io_v4l) { + ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT, + io_v4l, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + if (io_swradio) { + ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT, + io_swradio, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + if (io_vbi) { + ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT, + io_vbi, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + /* Create links for the media connectors */ + flags = MEDIA_LNK_FL_ENABLED; + media_device_for_each_entity(entity, mdev) { + switch (entity->function) { + case MEDIA_ENT_F_CONN_RF: + if (!tuner) + continue; + + ret = media_create_pad_link(entity, 0, tuner, + TUNER_PAD_RF_INPUT, + flags); + break; + case MEDIA_ENT_F_CONN_SVIDEO: + case MEDIA_ENT_F_CONN_COMPOSITE: + case MEDIA_ENT_F_CONN_TEST: + ret = media_create_pad_link(entity, 0, decoder, + DEMOD_PAD_IF_INPUT, + flags); + break; + default: + continue; + } + if (ret) + return ret; + + flags = 0; + } + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_mc_create_media_graph); diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index df115195690e..aed9e9b87f82 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -14,6 +14,8 @@ * GNU General Public License for more details. */ +#include + /** * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER * @@ -89,3 +91,26 @@ enum demod_pad_index { DEMOD_PAD_VBI_OUT, DEMOD_NUM_PADS }; + +/** + * v4l2_mc_create_media_graph() - create Media Controller links at the graph. + * + * @mdev: pointer to the &media_device struct. + * + * Add links between the entities commonly found on PC customer's hardware at + * the V4L2 side: camera sensors, audio and video PLL-IF decoders, tuners, + * analog TV decoder and I/O entities (video, VBI and Software Defined Radio). + * NOTE: webcams are modelled on a very simple way: the sensor is + * connected directly to the I/O entity. All dirty details, like + * scaler and crop HW are hidden. While such mapping is enough for v4l2 + * interface centric PC-consumer's hardware, V4L2 subdev centric camera + * hardware should not use this routine, as it will not build the right graph. + */ +#ifdef CONFIG_MEDIA_CONTROLLER +int v4l2_mc_create_media_graph(struct media_device *mdev); +#else +static inline int v4l2_mc_create_media_graph(struct media_device *mdev) +{ + return 0; +} +#endif -- cgit v1.2.3 From 2773b0e9baa68beed1f93d04a8ae8ca04b35a60d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 08:35:50 -0200 Subject: [media] add media controller support to videobuf2-dvb Allow devices to pass an optional argument to register the DVB driver at the media controller. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx23885/cx23885-dvb.c | 3 ++- drivers/media/pci/cx88/cx88-dvb.c | 3 ++- drivers/media/pci/netup_unidvb/netup_unidvb_core.c | 4 ++-- drivers/media/pci/saa7134/saa7134-dvb.c | 2 +- drivers/media/v4l2-core/videobuf2-dvb.c | 13 +++++++++++-- include/media/videobuf2-dvb.h | 5 +++++ 6 files changed, 23 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 80319bb73d94..5131c9f555fb 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -2301,7 +2301,8 @@ static int dvb_register(struct cx23885_tsport *port) /* register everything */ ret = vb2_dvb_register_bus(&port->frontends, THIS_MODULE, port, - &dev->pci->dev, adapter_nr, mfe_shared); + &dev->pci->dev, NULL, + adapter_nr, mfe_shared); if (ret) goto frontend_detach; diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c index afb20756d7a5..851d2a9caed3 100644 --- a/drivers/media/pci/cx88/cx88-dvb.c +++ b/drivers/media/pci/cx88/cx88-dvb.c @@ -1642,7 +1642,8 @@ static int dvb_register(struct cx8802_dev *dev) /* register everything */ res = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, - &dev->pci->dev, adapter_nr, mfe_shared); + &dev->pci->dev, NULL, adapter_nr, + mfe_shared); if (res) goto frontend_detach; return res; diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index c94cecd2aa40..2b667b315913 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c @@ -462,8 +462,8 @@ static int netup_unidvb_dvb_init(struct netup_unidvb_dev *ndev, } if (vb2_dvb_register_bus(&ndev->frontends[num], - THIS_MODULE, NULL, - &ndev->pci_dev->dev, adapter_nr, 1)) { + THIS_MODULE, NULL, + &ndev->pci_dev->dev, NULL, adapter_nr, 1)) { dev_dbg(&ndev->pci_dev->dev, "%s(): unable to register DVB bus %d\n", __func__, num); diff --git a/drivers/media/pci/saa7134/saa7134-dvb.c b/drivers/media/pci/saa7134/saa7134-dvb.c index 101ba8729416..ed84f7dea94c 100644 --- a/drivers/media/pci/saa7134/saa7134-dvb.c +++ b/drivers/media/pci/saa7134/saa7134-dvb.c @@ -1884,7 +1884,7 @@ static int dvb_init(struct saa7134_dev *dev) /* register everything else */ ret = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, - &dev->pci->dev, adapter_nr, 0); + &dev->pci->dev, NULL, adapter_nr, 0); /* this sequence is necessary to make the tda1004x load its firmware * and to enter analog mode of hybrid boards diff --git a/drivers/media/v4l2-core/videobuf2-dvb.c b/drivers/media/v4l2-core/videobuf2-dvb.c index d09269846b7e..9f38b4218c0d 100644 --- a/drivers/media/v4l2-core/videobuf2-dvb.c +++ b/drivers/media/v4l2-core/videobuf2-dvb.c @@ -77,6 +77,7 @@ static int vb2_dvb_register_adapter(struct vb2_dvb_frontends *fe, struct module *module, void *adapter_priv, struct device *device, + struct media_device *mdev, char *adapter_name, short *adapter_nr, int mfe_shared) @@ -94,7 +95,10 @@ static int vb2_dvb_register_adapter(struct vb2_dvb_frontends *fe, } fe->adapter.priv = adapter_priv; fe->adapter.mfe_shared = mfe_shared; - +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + if (mdev) + fe->adapter.mdev = mdev; +#endif return result; } @@ -193,6 +197,7 @@ int vb2_dvb_register_bus(struct vb2_dvb_frontends *f, struct module *module, void *adapter_priv, struct device *device, + struct media_device *mdev, short *adapter_nr, int mfe_shared) { @@ -207,7 +212,7 @@ int vb2_dvb_register_bus(struct vb2_dvb_frontends *f, } /* Bring up the adapter */ - res = vb2_dvb_register_adapter(f, module, adapter_priv, device, + res = vb2_dvb_register_adapter(f, module, adapter_priv, device, mdev, fe->dvb.name, adapter_nr, mfe_shared); if (res < 0) { pr_warn("vb2_dvb_register_adapter failed (errno = %d)\n", res); @@ -224,7 +229,11 @@ int vb2_dvb_register_bus(struct vb2_dvb_frontends *f, fe->dvb.name, res); goto err; } + res = dvb_create_media_graph(&f->adapter, false); + if (res < 0) + goto err; } + mutex_unlock(&f->lock); return 0; diff --git a/include/media/videobuf2-dvb.h b/include/media/videobuf2-dvb.h index 5b64c9eac2c9..87b559024b4a 100644 --- a/include/media/videobuf2-dvb.h +++ b/include/media/videobuf2-dvb.h @@ -8,6 +8,10 @@ #include #include + +/* We don't actually need to include media-device.h here */ +struct media_device; + /* * TODO: This header file should be replaced with videobuf2-core.h * Currently, vb2_thread is not a stuff of videobuf2-core, @@ -50,6 +54,7 @@ int vb2_dvb_register_bus(struct vb2_dvb_frontends *f, struct module *module, void *adapter_priv, struct device *device, + struct media_device *mdev, short *adapter_nr, int mfe_shared); -- cgit v1.2.3 From 7047f2982a223e0ecca480c11a37bd9edf62b65a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 13:16:18 -0200 Subject: [media] v4l2-mc: add an ancillary routine for PCI-based MC Instead of copyping the same code on all PCI devices that would have a media controller, add a core ancillary routine. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-mc.c | 35 +++++++++++++++++++++++++++++++++++ include/media/v4l2-mc.h | 24 +++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index e6d2a711bb0b..b6cf6dbd4cd5 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -15,9 +15,44 @@ */ #include +#include #include #include + +struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, + char *name) +{ +#ifdef CONFIG_PCI + struct media_device *mdev; + + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return NULL; + + mdev->dev = &pci_dev->dev; + + if (name) + strlcpy(mdev->model, name, sizeof(mdev->model)); + else + strlcpy(mdev->model, pci_name(pci_dev), sizeof(mdev->model)); + + sprintf(mdev->bus_info, "PCI:%s", pci_name(pci_dev)); + + mdev->hw_revision = pci_dev->subsystem_vendor << 16 + || pci_dev->subsystem_device; + + mdev->driver_version = LINUX_VERSION_CODE; + + media_device_init(mdev); + + return mdev; +#else + return NULL; +#endif +} +EXPORT_SYMBOL_GPL(v4l2_mc_pci_media_device_init); + int v4l2_mc_create_media_graph(struct media_device *mdev) { diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index aed9e9b87f82..6fad97277a0b 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -92,6 +92,10 @@ enum demod_pad_index { DEMOD_NUM_PADS }; + +struct pci_dev; /* We don't need to include pci.h here */ + +#ifdef CONFIG_MEDIA_CONTROLLER /** * v4l2_mc_create_media_graph() - create Media Controller links at the graph. * @@ -106,11 +110,29 @@ enum demod_pad_index { * interface centric PC-consumer's hardware, V4L2 subdev centric camera * hardware should not use this routine, as it will not build the right graph. */ -#ifdef CONFIG_MEDIA_CONTROLLER int v4l2_mc_create_media_graph(struct media_device *mdev); + +/** + * v4l2_mc_pci_media_device_init() - create and initialize a + * struct &media_device from a PCI device. + * + * @pci_dev: pointer to struct pci_dev + * @name: media device name. If %NULL, the routine will use the default + * name for the pci device, given by pci_name() macro. + */ +struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, + char *name); + + #else static inline int v4l2_mc_create_media_graph(struct media_device *mdev) { return 0; } + +struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, + char *name) { + return NULL; +} + #endif -- cgit v1.2.3 From 45cc29afb47f229014257068a3153276b2fb4c38 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 27 Jan 2016 11:31:39 -0200 Subject: [media] v4l2-ctrls: add V4L2_CID_DV_RX/TX_IT_CONTENT_TYPE controls HDMI and DisplayPort both support IT Content Type information that tells the receiver what type of material the video is, graphics such as from a PC desktop, Photo, Cinema or Game (low-latency). This patch adds controls for receivers and transmitters to get/set this information. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ctrls.c | 16 ++++++++++++++++ include/uapi/linux/v4l2-controls.h | 10 ++++++++++ 2 files changed, 26 insertions(+) (limited to 'include') diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index c9d5537b6af7..bed04b1fdd0a 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -462,6 +462,14 @@ const char * const *v4l2_ctrl_get_menu(u32 id) "RGB full range (0-255)", NULL, }; + static const char * const dv_it_content_type[] = { + "Graphics", + "Photo", + "Cinema", + "Game", + "No IT Content", + NULL, + }; static const char * const detect_md_mode[] = { "Disabled", "Global", @@ -560,6 +568,9 @@ const char * const *v4l2_ctrl_get_menu(u32 id) case V4L2_CID_DV_TX_RGB_RANGE: case V4L2_CID_DV_RX_RGB_RANGE: return dv_rgb_range; + case V4L2_CID_DV_TX_IT_CONTENT_TYPE: + case V4L2_CID_DV_RX_IT_CONTENT_TYPE: + return dv_it_content_type; case V4L2_CID_DETECT_MD_MODE: return detect_md_mode; @@ -881,8 +892,10 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_DV_TX_EDID_PRESENT: return "EDID Present"; case V4L2_CID_DV_TX_MODE: return "Transmit Mode"; case V4L2_CID_DV_TX_RGB_RANGE: return "Tx RGB Quantization Range"; + case V4L2_CID_DV_TX_IT_CONTENT_TYPE: return "Tx IT Content Type"; case V4L2_CID_DV_RX_POWER_PRESENT: return "Power Present"; case V4L2_CID_DV_RX_RGB_RANGE: return "Rx RGB Quantization Range"; + case V4L2_CID_DV_RX_IT_CONTENT_TYPE: return "Rx IT Content Type"; case V4L2_CID_FM_RX_CLASS: return "FM Radio Receiver Controls"; case V4L2_CID_TUNE_DEEMPHASIS: return "De-Emphasis"; @@ -1038,7 +1051,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_SCENE_MODE: case V4L2_CID_DV_TX_MODE: case V4L2_CID_DV_TX_RGB_RANGE: + case V4L2_CID_DV_TX_IT_CONTENT_TYPE: case V4L2_CID_DV_RX_RGB_RANGE: + case V4L2_CID_DV_RX_IT_CONTENT_TYPE: case V4L2_CID_TEST_PATTERN: case V4L2_CID_TUNE_DEEMPHASIS: case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: @@ -1185,6 +1200,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_DV_TX_RXSENSE: case V4L2_CID_DV_TX_EDID_PRESENT: case V4L2_CID_DV_RX_POWER_PRESENT: + case V4L2_CID_DV_RX_IT_CONTENT_TYPE: case V4L2_CID_RDS_RX_PTY: case V4L2_CID_RDS_RX_PS_NAME: case V4L2_CID_RDS_RX_RADIO_TEXT: diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 2d225bcdb831..2ae5c3ea179b 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -912,8 +912,18 @@ enum v4l2_dv_rgb_range { V4L2_DV_RGB_RANGE_FULL = 2, }; +#define V4L2_CID_DV_TX_IT_CONTENT_TYPE (V4L2_CID_DV_CLASS_BASE + 6) +enum v4l2_dv_it_content_type { + V4L2_DV_IT_CONTENT_TYPE_GRAPHICS = 0, + V4L2_DV_IT_CONTENT_TYPE_PHOTO = 1, + V4L2_DV_IT_CONTENT_TYPE_CINEMA = 2, + V4L2_DV_IT_CONTENT_TYPE_GAME = 3, + V4L2_DV_IT_CONTENT_TYPE_NO_ITC = 4, +}; + #define V4L2_CID_DV_RX_POWER_PRESENT (V4L2_CID_DV_CLASS_BASE + 100) #define V4L2_CID_DV_RX_RGB_RANGE (V4L2_CID_DV_CLASS_BASE + 101) +#define V4L2_CID_DV_RX_IT_CONTENT_TYPE (V4L2_CID_DV_CLASS_BASE + 102) #define V4L2_CID_FM_RX_CLASS_BASE (V4L2_CTRL_CLASS_FM_RX | 0x900) #define V4L2_CID_FM_RX_CLASS (V4L2_CTRL_CLASS_FM_RX | 1) -- cgit v1.2.3 From 8ddc2dd0832e062bbb36e965e5a202a7d0b584a0 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Tue, 3 Nov 2015 21:50:23 -0200 Subject: [media] v4l2-ctrls: remove unclaimed v4l2_ctrl_add_ctrl() interface v4l2_ctrl_add_ctrl() interface has no users since its introduction in commit 0996517cf8ea ("V4L/DVB: v4l2: Add new control handling framework") and its functionality is covered by v4l2_ctrl_new() and derivative interfaces, so it is safe to remove the interface from the kernel. Signed-off-by: Vladimir Zapolskiy Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-controls.txt | 1 - drivers/media/v4l2-core/v4l2-ctrls.c | 16 ---------------- include/media/v4l2-ctrls.h | 12 ------------ 3 files changed, 29 deletions(-) (limited to 'include') diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt index 5517db602f37..5e759cab4538 100644 --- a/Documentation/video4linux/v4l2-controls.txt +++ b/Documentation/video4linux/v4l2-controls.txt @@ -647,7 +647,6 @@ Or you can add specific controls to a handler: volume = v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_AUDIO_VOLUME, ...); v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_BRIGHTNESS, ...); v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_CONTRAST, ...); - v4l2_ctrl_add_ctrl(&radio_ctrl_handler, volume); What you should not do is make two identical controls for two handlers. For example: diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index bed04b1fdd0a..130e5badd599 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -2227,22 +2227,6 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, } EXPORT_SYMBOL(v4l2_ctrl_new_int_menu); -/* Add a control from another handler to this handler */ -struct v4l2_ctrl *v4l2_ctrl_add_ctrl(struct v4l2_ctrl_handler *hdl, - struct v4l2_ctrl *ctrl) -{ - if (hdl == NULL || hdl->error) - return NULL; - if (ctrl == NULL) { - handler_set_err(hdl, -EINVAL); - return NULL; - } - if (ctrl->handler == hdl) - return ctrl; - return handler_new_ref(hdl, ctrl) ? NULL : ctrl; -} -EXPORT_SYMBOL(v4l2_ctrl_add_ctrl); - /* Add the controls from another handler to our own. */ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl_handler *add, diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index da6fe9802fee..0bc9b35b8f3e 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -534,18 +534,6 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, u8 max, u8 def, const s64 *qmenu_int); -/** - * v4l2_ctrl_add_ctrl() - Add a control from another handler to this handler. - * @hdl: The control handler. - * @ctrl: The control to add. - * - * It will return NULL if it was unable to add the control reference. - * If the control already belonged to the handler, then it will do - * nothing and just return @ctrl. - */ -struct v4l2_ctrl *v4l2_ctrl_add_ctrl(struct v4l2_ctrl_handler *hdl, - struct v4l2_ctrl *ctrl); - /** * v4l2_ctrl_add_handler() - Add all controls from handler @add to * handler @hdl. -- cgit v1.2.3 From 798bd945f0606dfe615142e1157e8ab5c7d29e2b Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:51 -0200 Subject: [media] v4l2-subdev: add registered_async subdev core operation V4L2 sub-devices that are registered asynchronously have no way to know when they have been registration with a V4L2 device but they might need to take some action after this. So let's add a callback that can be executed by the V4L2 async core to allow sub-devices drivers to do any needed initialization that depends on the registration. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-subdev.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index b273cf9ac047..11e2dfec0198 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -179,6 +179,8 @@ struct v4l2_subdev_io_pin_config { * for it to be warned when the value of a control changes. * * @unsubscribe_event: remove event subscription from the control framework. + * + * @registered_async: the subdevice has been registered async. */ struct v4l2_subdev_core_ops { int (*log_status)(struct v4l2_subdev *sd); @@ -211,6 +213,7 @@ struct v4l2_subdev_core_ops { struct v4l2_event_subscription *sub); int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh, struct v4l2_event_subscription *sub); + int (*registered_async)(struct v4l2_subdev *sd); }; /** -- cgit v1.2.3 From f38f2622f876609c3dc2865bbd937be22bad5a42 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:55 -0200 Subject: [media] tvp5150: add internal signal generator to HW input list Some tvp5150 variants, have an internal generator that can generate a black screen output. Since this is a HW block, it should be in the HW inputs list. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- include/media/i2c/tvp5150.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/media/i2c/tvp5150.h b/include/media/i2c/tvp5150.h index 649908a25605..685a1e718531 100644 --- a/include/media/i2c/tvp5150.h +++ b/include/media/i2c/tvp5150.h @@ -25,6 +25,7 @@ #define TVP5150_COMPOSITE0 0 #define TVP5150_COMPOSITE1 1 #define TVP5150_SVIDEO 2 +#define TVP5150_GENERATOR 3 /* TVP5150 HW outputs */ #define TVP5150_NORMAL 0 -- cgit v1.2.3 From b802fb99ae964681d1754428f67970911e0476e9 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:56 -0200 Subject: [media] tvp5150: move input definition header to dt-bindings Add a header file for the tvp5150 input connectors constants that can be shared between the driver and Device Tree source files. [mchehab@osg.samsung.com: rename tvp5150.h also at em28xx-cards.c] Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 2 +- drivers/media/usb/em28xx/em28xx-cards.c | 2 +- include/dt-bindings/media/tvp5150.h | 34 +++++++++++++++++++++++++++++++++ include/media/i2c/tvp5150.h | 34 --------------------------------- 4 files changed, 36 insertions(+), 36 deletions(-) create mode 100644 include/dt-bindings/media/tvp5150.h delete mode 100644 include/media/i2c/tvp5150.h (limited to 'include') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 093ff80f944c..3a32fd1df805 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -5,6 +5,7 @@ * This code is placed under the terms of the GNU General Public License v2 */ +#include #include #include #include @@ -13,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index ba442c967415..06a09b4e4a83 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/dt-bindings/media/tvp5150.h b/include/dt-bindings/media/tvp5150.h new file mode 100644 index 000000000000..dc347569854f --- /dev/null +++ b/include/dt-bindings/media/tvp5150.h @@ -0,0 +1,34 @@ +/* + tvp5150.h - definition for tvp5150 inputs + + Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _DT_BINDINGS_MEDIA_TVP5150_H +#define _DT_BINDINGS_MEDIA_TVP5150_H + +/* TVP5150 HW inputs */ +#define TVP5150_COMPOSITE0 0 +#define TVP5150_COMPOSITE1 1 +#define TVP5150_SVIDEO 2 +#define TVP5150_GENERATOR 3 + +/* TVP5150 HW outputs */ +#define TVP5150_NORMAL 0 +#define TVP5150_BLACK_SCREEN 1 + +#endif /* _DT_BINDINGS_MEDIA_TVP5150_H */ diff --git a/include/media/i2c/tvp5150.h b/include/media/i2c/tvp5150.h deleted file mode 100644 index 685a1e718531..000000000000 --- a/include/media/i2c/tvp5150.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - tvp5150.h - definition for tvp5150 inputs - - Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _TVP5150_H_ -#define _TVP5150_H_ - -/* TVP5150 HW inputs */ -#define TVP5150_COMPOSITE0 0 -#define TVP5150_COMPOSITE1 1 -#define TVP5150_SVIDEO 2 -#define TVP5150_GENERATOR 3 - -/* TVP5150 HW outputs */ -#define TVP5150_NORMAL 0 -#define TVP5150_BLACK_SCREEN 1 - -#endif -- cgit v1.2.3 From f7b4b54e63643b740c598e044874c4bffa0f04f2 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:58 -0200 Subject: [media] tvp5150: add HW input connectors support The tvp5150 decoder has different input connectors. The actual list of HW inputs depends on the device version but all have at least these 3: 1) Composite0 2) Composite1 3) S-Video and some variants have a 4th possible input connector: 4) Signal generator The driver currently uses the .s_routing callback to switch the input connector but since these are separate HW blocks, it's better to use media entities to represent the input connectors and their source pads linked with the decoder's sink pad. This allows user-space to use the MEDIA_IOC_SETUP_LINK ioctl to choose the input connector. For example using the media-ctl user-space tool: $ media-ctl -r -l '"Composite0":0->"tvp5150 1-005c":0[1]' Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 150 ++++++++++++++++++++++++++++++++++++ include/dt-bindings/media/tvp5150.h | 2 + 2 files changed, 152 insertions(+) (limited to 'include') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 3a32fd1df805..b8976028fc82 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -40,6 +40,8 @@ struct tvp5150 { struct v4l2_subdev sd; #ifdef CONFIG_MEDIA_CONTROLLER struct media_pad pads[DEMOD_NUM_PADS]; + struct media_entity input_ent[TVP5150_INPUT_NUM]; + struct media_pad input_pad[TVP5150_INPUT_NUM]; #endif struct v4l2_ctrl_handler hdl; struct v4l2_rect rect; @@ -996,6 +998,49 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd, return 0; } +/**************************************************************************** + Media entity ops + ****************************************************************************/ + +static int tvp5150_link_setup(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); + struct tvp5150 *decoder = to_tvp5150(sd); + int i; + + for (i = 0; i < TVP5150_INPUT_NUM; i++) { + if (remote->entity == &decoder->input_ent[i]) + break; + } + + /* Do nothing for entities that are not input connectors */ + if (i == TVP5150_INPUT_NUM) + return 0; + + decoder->input = i; + + /* Only tvp5150am1 and tvp5151 have signal generator support */ + if ((decoder->dev_id == 0x5150 && decoder->rom_ver == 0x0400) || + (decoder->dev_id == 0x5151 && decoder->rom_ver == 0x0100)) { + decoder->output = (i == TVP5150_GENERATOR ? + TVP5150_BLACK_SCREEN : TVP5150_NORMAL); + } else { + decoder->output = TVP5150_NORMAL; + } + + tvp5150_selmux(sd); +#endif + + return 0; +} + +static const struct media_entity_operations tvp5150_sd_media_ops = { + .link_setup = tvp5150_link_setup, +}; + /**************************************************************************** I2C Command ****************************************************************************/ @@ -1122,6 +1167,42 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; } +static int tvp5150_registered_async(struct v4l2_subdev *sd) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct tvp5150 *decoder = to_tvp5150(sd); + int ret = 0; + int i; + + for (i = 0; i < TVP5150_INPUT_NUM; i++) { + struct media_entity *input = &decoder->input_ent[i]; + struct media_pad *pad = &decoder->input_pad[i]; + + if (!input->name) + continue; + + decoder->input_pad[i].flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(input, 1, pad); + if (ret < 0) + return ret; + + ret = media_device_register_entity(sd->v4l2_dev->mdev, input); + if (ret < 0) + return ret; + + ret = media_create_pad_link(input, 0, &sd->entity, + DEMOD_PAD_IF_INPUT, 0); + if (ret < 0) { + media_device_unregister_entity(input); + return ret; + } + } +#endif + + return 0; +} + /* ----------------------------------------------------------------------- */ static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = { @@ -1135,6 +1216,7 @@ static const struct v4l2_subdev_core_ops tvp5150_core_ops = { .g_register = tvp5150_g_register, .s_register = tvp5150_s_register, #endif + .registered_async = tvp5150_registered_async, }; static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = { @@ -1255,6 +1337,12 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) { struct v4l2_of_endpoint bus_cfg; struct device_node *ep; +#ifdef CONFIG_MEDIA_CONTROLLER + struct device_node *connectors, *child; + struct media_entity *input; + const char *name; + u32 input_type; +#endif unsigned int flags; int ret = 0; @@ -1278,6 +1366,66 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) decoder->mbus_type = bus_cfg.bus_type; +#ifdef CONFIG_MEDIA_CONTROLLER + connectors = of_get_child_by_name(np, "connectors"); + + if (!connectors) + goto err; + + for_each_available_child_of_node(connectors, child) { + ret = of_property_read_u32(child, "input", &input_type); + if (ret) { + v4l2_err(&decoder->sd, + "missing type property in node %s\n", + child->name); + goto err_connector; + } + + if (input_type > TVP5150_INPUT_NUM) { + ret = -EINVAL; + goto err_connector; + } + + input = &decoder->input_ent[input_type]; + + /* Each input connector can only be defined once */ + if (input->name) { + v4l2_err(&decoder->sd, + "input %s with same type already exists\n", + input->name); + ret = -EINVAL; + goto err_connector; + } + + switch (input_type) { + case TVP5150_COMPOSITE0: + case TVP5150_COMPOSITE1: + input->function = MEDIA_ENT_F_CONN_COMPOSITE; + break; + case TVP5150_SVIDEO: + input->function = MEDIA_ENT_F_CONN_SVIDEO; + break; + case TVP5150_GENERATOR: + input->function = MEDIA_ENT_F_CONN_TEST; + break; + } + + input->flags = MEDIA_ENT_FL_CONNECTOR; + + ret = of_property_read_string(child, "label", &name); + if (ret < 0) { + v4l2_err(&decoder->sd, + "missing label property in node %s\n", + child->name); + goto err_connector; + } + + input->name = name; + } + +err_connector: + of_node_put(connectors); +#endif err: of_node_put(ep); return ret; @@ -1330,6 +1478,8 @@ static int tvp5150_probe(struct i2c_client *c, res = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, core->pads); if (res < 0) return res; + + sd->entity.ops = &tvp5150_sd_media_ops; #endif res = tvp5150_detect_version(core); diff --git a/include/dt-bindings/media/tvp5150.h b/include/dt-bindings/media/tvp5150.h index dc347569854f..d30865222082 100644 --- a/include/dt-bindings/media/tvp5150.h +++ b/include/dt-bindings/media/tvp5150.h @@ -27,6 +27,8 @@ #define TVP5150_SVIDEO 2 #define TVP5150_GENERATOR 3 +#define TVP5150_INPUT_NUM 4 + /* TVP5150 HW outputs */ #define TVP5150_NORMAL 0 #define TVP5150_BLACK_SCREEN 1 -- cgit v1.2.3 From db152276ce720baadcbd6bccebbeb17da001d312 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Feb 2016 07:35:44 -0200 Subject: [media] v4l2-mc.h: prevent it for being included twice Don't let it be included twice, to avoid compiler issues. Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-mc.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 6fad97277a0b..20f1ee285947 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -14,6 +14,9 @@ * GNU General Public License for more details. */ +#ifndef _V4L2_MC_H +#define _V4L2_MC_H + #include /** @@ -136,3 +139,5 @@ struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, } #endif + +#endif -- cgit v1.2.3 From eee7d353a19032b48c0f71504081de84a0ee79d8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Feb 2016 15:21:46 -0200 Subject: [media] v4l2-mc: add a routine to create USB media_device Instead of copying exactly the same code on all USB devices, add an ancillary routine that will create and fill the struct media_device with the values imported from the USB device. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-mc.c | 41 ++++++++++++++++++++++++++++++++++++++- include/media/v4l2-mc.h | 39 ++++++++++++++++++++++++++++++++----- 2 files changed, 74 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index b6cf6dbd4cd5..97b2e1e64d2e 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -16,12 +16,13 @@ #include #include +#include #include #include struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, - char *name) + const char *name) { #ifdef CONFIG_PCI struct media_device *mdev; @@ -53,6 +54,44 @@ struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, } EXPORT_SYMBOL_GPL(v4l2_mc_pci_media_device_init); +struct media_device *__v4l2_mc_usb_media_device_init(struct usb_device *udev, + const char *board_name, + const char *driver_name) +{ +#ifdef CONFIG_USB + struct media_device *mdev; + + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return NULL; + + mdev->dev = &udev->dev; + + if (driver_name) + strlcpy(mdev->driver_name, driver_name, + sizeof(mdev->driver_name)); + + if (board_name) + strlcpy(mdev->model, board_name, sizeof(mdev->model)); + else if (udev->product) + strlcpy(mdev->model, udev->product, sizeof(mdev->model)); + else + strlcpy(mdev->model, "unknown model", sizeof(mdev->model)); + if (udev->serial) + strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); + usb_make_path(udev, mdev->bus_info, sizeof(mdev->bus_info)); + mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); + mdev->driver_version = LINUX_VERSION_CODE; + + media_device_init(mdev); + + return mdev; +#else + return NULL; +#endif +} +EXPORT_SYMBOL_GPL(__v4l2_mc_usb_media_device_init); + int v4l2_mc_create_media_graph(struct media_device *mdev) { diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 20f1ee285947..79d84bb3573c 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -95,8 +95,9 @@ enum demod_pad_index { DEMOD_NUM_PADS }; - -struct pci_dev; /* We don't need to include pci.h here */ +/* We don't need to include pci.h or usb.h here */ +struct pci_dev; +struct usb_device; #ifdef CONFIG_MEDIA_CONTROLLER /** @@ -124,8 +125,24 @@ int v4l2_mc_create_media_graph(struct media_device *mdev); * name for the pci device, given by pci_name() macro. */ struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, - char *name); - + const char *name); +/** + * __v4l2_mc_usb_media_device_init() - create and initialize a + * struct &media_device from a PCI device. + * + * @udev: pointer to struct usb_device + * @board_name: media device name. If %NULL, the routine will use the usb + * product name, if available. + * @driver_name: name of the driver. if %NULL, the routine will use the name + * given by udev->dev->driver->name, with is usually the wrong + * thing to do. + * + * NOTE: It is better to call v4l2_mc_usb_media_device_init() instead, as + * such macro fills driver_name with %KBUILD_MODNAME. + */ +struct media_device *__v4l2_mc_usb_media_device_init(struct usb_device *udev, + const char *board_name, + const char *driver_name); #else static inline int v4l2_mc_create_media_graph(struct media_device *mdev) @@ -133,11 +150,23 @@ static inline int v4l2_mc_create_media_graph(struct media_device *mdev) return 0; } +static inline struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, - char *name) { + char *name) +{ return NULL; } +static inline +struct media_device *__v4l2_mc_usb_media_device_init(struct usb_device *udev, + char *board_name, + char *driver_name) +{ + return NULL; +} #endif +#define v4l2_mc_usb_media_device_init(udev, name) \ + __v4l2_mc_usb_media_device_init(udev, name, KBUILD_MODNAME) + #endif -- cgit v1.2.3 From c73bbaa4ec3eb225ffe468f80d45724d0496bf03 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Feb 2016 10:33:31 -0200 Subject: [media] rc-core: don't lock device at rc_register_device() The mutex lock at rc_register_device() was added by commit 08aeb7c9a42a ("[media] rc: add locking to fix register/show race"). It is meant to avoid race issues when trying to open a sysfs file while the RC register didn't complete. Adding a lock there causes troubles, as detected by the Kernel lock debug instrumentation at the Kernel: ====================================================== [ INFO: possible circular locking dependency detected ] 4.5.0-rc3+ #46 Not tainted ------------------------------------------------------- systemd-udevd/2681 is trying to acquire lock: (s_active#171){++++.+}, at: [] kernfs_remove_by_name_ns+0x45/0xa0 but task is already holding lock: (&dev->lock){+.+.+.}, at: [] rc_register_device+0xb2f/0x1450 [rc_core] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&dev->lock){+.+.+.}: [] lock_acquire+0x13d/0x320 [] mutex_lock_nested+0xb6/0x860 [] show_protocols+0x3b/0x3f0 [rc_core] [] dev_attr_show+0x45/0xc0 [] sysfs_kf_seq_show+0x203/0x3c0 [] kernfs_seq_show+0x121/0x1b0 [] seq_read+0x2f1/0x1160 [] kernfs_fop_read+0x321/0x460 [] __vfs_read+0xe0/0x3d0 [] vfs_read+0xde/0x2d0 [] SyS_read+0x111/0x230 [] entry_SYSCALL_64_fastpath+0x16/0x76 -> #0 (s_active#171){++++.+}: [] __lock_acquire+0x4304/0x5990 [] lock_acquire+0x13d/0x320 [] __kernfs_remove+0x58a/0x810 [] kernfs_remove_by_name_ns+0x45/0xa0 [] remove_files.isra.0+0x72/0x190 [] sysfs_remove_group+0x9b/0x150 [] sysfs_remove_groups+0x54/0xa0 [] device_remove_attrs+0xb0/0x140 [] device_del+0x38c/0x6b0 [] rc_register_device+0x8cb/0x1450 [rc_core] [] dvb_usb_remote_init+0x66b/0x14d0 [dvb_usb] [] dvb_usb_device_init+0xf21/0x1860 [dvb_usb] [] dib0700_probe+0x14c/0x410 [dvb_usb_dib0700] [] usb_probe_interface+0x45d/0x940 [] driver_probe_device+0x21a/0xc30 [] __driver_attach+0x121/0x160 [] bus_for_each_dev+0x11f/0x1a0 [] driver_attach+0x3d/0x50 [] bus_add_driver+0x4c9/0x770 [] driver_register+0x18c/0x3b0 [] usb_register_driver+0x1f8/0x440 [] dib0700_driver_init+0x1e/0x1000 [dvb_usb_dib0700] [] do_one_initcall+0x141/0x300 [] do_init_module+0x1d0/0x5ad [] load_module+0x6666/0x9ba0 [] SyS_finit_module+0x108/0x130 [] entry_SYSCALL_64_fastpath+0x16/0x76 other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&dev->lock); lock(s_active#171); lock(&dev->lock); lock(s_active#171); *** DEADLOCK *** 3 locks held by systemd-udevd/2681: #0: (&dev->mutex){......}, at: [] __driver_attach+0xa3/0x160 #1: (&dev->mutex){......}, at: [] __driver_attach+0xb1/0x160 #2: (&dev->lock){+.+.+.}, at: [] rc_register_device+0xb2f/0x1450 [rc_core] In this specific case, some error happened during device init, causing IR to be disabled. Let's fix it by adding a var that will tell when the device is initialized. Any calls before that will return a -EINVAL. That should prevent the race issues. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-main.c | 45 ++++++++++++++++++++++++++------------------- include/media/rc-core.h | 2 ++ 2 files changed, 28 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 1042fa331a07..dcf20d9cbe09 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -723,12 +723,18 @@ int rc_open(struct rc_dev *rdev) return -EINVAL; mutex_lock(&rdev->lock); + if (!rdev->initialized) { + rval = -EINVAL; + goto unlock; + } + if (!rdev->users++ && rdev->open != NULL) rval = rdev->open(rdev); if (rval) rdev->users--; +unlock: mutex_unlock(&rdev->lock); return rval; @@ -874,6 +880,10 @@ static ssize_t show_protocols(struct device *device, return -EINVAL; mutex_lock(&dev->lock); + if (!dev->initialized) { + mutex_unlock(&dev->lock); + return -EINVAL; + } if (fattr->type == RC_FILTER_NORMAL) { enabled = dev->enabled_protocols; @@ -1074,6 +1084,10 @@ static ssize_t store_protocols(struct device *device, } mutex_lock(&dev->lock); + if (!dev->initialized) { + rc = -EINVAL; + goto out; + } old_protocols = *current_protocols; new_protocols = old_protocols; @@ -1154,12 +1168,17 @@ static ssize_t show_filter(struct device *device, if (!dev) return -EINVAL; + mutex_lock(&dev->lock); + if (!dev->initialized) { + mutex_unlock(&dev->lock); + return -EINVAL; + } + if (fattr->type == RC_FILTER_NORMAL) filter = &dev->scancode_filter; else filter = &dev->scancode_wakeup_filter; - mutex_lock(&dev->lock); if (fattr->mask) val = filter->mask; else @@ -1222,6 +1241,10 @@ static ssize_t store_filter(struct device *device, return -EINVAL; mutex_lock(&dev->lock); + if (!dev->initialized) { + ret = -EINVAL; + goto unlock; + } new_filter = *filter; if (fattr->mask) @@ -1419,14 +1442,6 @@ int rc_register_device(struct rc_dev *dev) dev->sysfs_groups[attr++] = &rc_dev_wakeup_protocol_attr_grp; dev->sysfs_groups[attr++] = NULL; - /* - * Take the lock here, as the device sysfs node will appear - * when device_add() is called, which may trigger an ir-keytable udev - * rule, which will in turn call show_protocols and access - * dev->enabled_protocols before it has been initialized. - */ - mutex_lock(&dev->lock); - rc = device_add(&dev->dev); if (rc) goto out_unlock; @@ -1440,13 +1455,7 @@ int rc_register_device(struct rc_dev *dev) dev->input_dev->phys = dev->input_phys; dev->input_dev->name = dev->input_name; - /* input_register_device can call ir_open, so unlock mutex here */ - mutex_unlock(&dev->lock); - rc = input_register_device(dev->input_dev); - - mutex_lock(&dev->lock); - if (rc) goto out_table; @@ -1475,10 +1484,7 @@ int rc_register_device(struct rc_dev *dev) request_module_nowait("ir-lirc-codec"); raw_init = true; } - /* calls ir_register_device so unlock mutex here*/ - mutex_unlock(&dev->lock); rc = ir_raw_event_register(dev); - mutex_lock(&dev->lock); if (rc < 0) goto out_input; } @@ -1491,6 +1497,8 @@ int rc_register_device(struct rc_dev *dev) dev->enabled_protocols = rc_type; } + mutex_lock(&dev->lock); + dev->initialized = true; mutex_unlock(&dev->lock); IR_dprintk(1, "Registered rc%u (driver: %s, remote: %s, mode %s)\n", @@ -1512,7 +1520,6 @@ out_table: out_dev: device_del(&dev->dev); out_unlock: - mutex_unlock(&dev->lock); ida_simple_remove(&rc_ida, minor); return rc; } diff --git a/include/media/rc-core.h b/include/media/rc-core.h index f6494709e230..c41dd7018fa8 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -60,6 +60,7 @@ enum rc_filter_type { /** * struct rc_dev - represents a remote control device * @dev: driver model's view of this device + * @initialized: true if the device init has completed * @sysfs_groups: sysfs attribute groups * @input_name: name of the input child device * @input_phys: physical path to the input child device @@ -121,6 +122,7 @@ enum rc_filter_type { */ struct rc_dev { struct device dev; + bool initialized; const struct attribute_group *sysfs_groups[5]; const char *input_name; const char *input_phys; -- cgit v1.2.3 From bb07bd6b6851120ac9b25bb315d62d9782d2c345 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Feb 2016 14:24:23 -0200 Subject: [media] allow overriding the driver name On USB drivers, the dev struct is usually filled with the USB device. That would mean that the name of the driver specified by media_device.dev.driver.name would be "usb", instead of the name of the actual driver that created the media entity. Add an optional field at the internal struct to allow drivers to override the driver name. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-device.c | 6 +++++- include/media/media-device.h | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 4d1c13de494b..5ebb3cd31345 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -55,7 +55,11 @@ static int media_device_get_info(struct media_device *dev, memset(&info, 0, sizeof(info)); - strlcpy(info.driver, dev->dev->driver->name, sizeof(info.driver)); + if (dev->driver_name[0]) + strlcpy(info.driver, dev->driver_name, sizeof(info.driver)); + else + strlcpy(info.driver, dev->dev->driver->name, sizeof(info.driver)); + strlcpy(info.model, dev->model, sizeof(info.model)); strlcpy(info.serial, dev->serial, sizeof(info.serial)); strlcpy(info.bus_info, dev->bus_info, sizeof(info.bus_info)); diff --git a/include/media/media-device.h b/include/media/media-device.h index d3855898c3fc..165451bc3985 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -268,6 +268,10 @@ struct device; * struct media_device - Media device * @dev: Parent device * @devnode: Media device node + * @driver_name: Optional device driver name. If not set, calls to + * %MEDIA_IOC_DEVICE_INFO will return dev->driver->name. + * This is needed for USB drivers for example, as otherwise + * they'll all appear as if the driver name was "usb". * @model: Device model name * @serial: Device serial number (optional) * @bus_info: Unique and stable device location identifier @@ -303,6 +307,7 @@ struct media_device { struct media_devnode devnode; char model[32]; + char driver_name[32]; char serial[40]; char bus_info[32]; u32 hw_revision; -- cgit v1.2.3 From c43875f66140f5457f90fc5f6f6840c74b2762cd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Feb 2016 15:42:02 -0200 Subject: [media] tvp5150: replace MEDIA_ENT_F_CONN_TEST by a control MEDIA_ENT_F_CONN_TEST is not really a connector, it is actually a signal generator. Also, as other drivers use the V4L2_CID_TEST_PATTERN control for signal generators, let's change the driver accordingly. Tested with Terratec Grabster AV350. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 45 +++++++++++++++++++++++-------------- include/dt-bindings/media/tvp5150.h | 3 +-- 2 files changed, 29 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index b8976028fc82..ef393f5daf2a 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1,5 +1,5 @@ /* - * tvp5150 - Texas Instruments TVP5150A/AM1 video decoder driver + * tvp5150 - Texas Instruments TVP5150A/AM1 and TVP5151 video decoder driver * * Copyright (c) 2005,2006 Mauro Carvalho Chehab (mchehab@infradead.org) * This code is placed under the terms of the GNU General Public License v2 @@ -27,7 +27,7 @@ #define TVP5150_MAX_CROP_TOP 127 #define TVP5150_CROP_SHIFT 2 -MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); +MODULE_DESCRIPTION("Texas Instruments TVP5150A/TVP5150AM1/TVP5151 video decoder driver"); MODULE_AUTHOR("Mauro Carvalho Chehab"); MODULE_LICENSE("GPL"); @@ -259,8 +259,12 @@ static inline void tvp5150_selmux(struct v4l2_subdev *sd) int input = 0; int val; - if ((decoder->output & TVP5150_BLACK_SCREEN) || !decoder->enable) - input = 8; + /* Only tvp5150am1 and tvp5151 have signal generator support */ + if ((decoder->dev_id == 0x5150 && decoder->rom_ver == 0x0400) || + (decoder->dev_id == 0x5151 && decoder->rom_ver == 0x0100)) { + if (!decoder->enable) + input = 8; + } switch (decoder->input) { case TVP5150_COMPOSITE1: @@ -795,6 +799,7 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val) static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl) { struct v4l2_subdev *sd = to_sd(ctrl); + struct tvp5150 *decoder = to_tvp5150(sd); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: @@ -808,6 +813,9 @@ static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl) return 0; case V4L2_CID_HUE: tvp5150_write(sd, TVP5150_HUE_CTL, ctrl->val); + case V4L2_CID_TEST_PATTERN: + decoder->enable = ctrl->val ? false : true; + tvp5150_selmux(sd); return 0; } return -EINVAL; @@ -1022,15 +1030,6 @@ static int tvp5150_link_setup(struct media_entity *entity, decoder->input = i; - /* Only tvp5150am1 and tvp5151 have signal generator support */ - if ((decoder->dev_id == 0x5150 && decoder->rom_ver == 0x0400) || - (decoder->dev_id == 0x5151 && decoder->rom_ver == 0x0100)) { - decoder->output = (i == TVP5150_GENERATOR ? - TVP5150_BLACK_SCREEN : TVP5150_NORMAL); - } else { - decoder->output = TVP5150_NORMAL; - } - tvp5150_selmux(sd); #endif @@ -1074,6 +1073,12 @@ static int tvp5150_s_routing(struct v4l2_subdev *sd, decoder->input = input; decoder->output = output; + + if (output == TVP5150_BLACK_SCREEN) + decoder->enable = false; + else + decoder->enable = true; + tvp5150_selmux(sd); return 0; } @@ -1405,9 +1410,6 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) case TVP5150_SVIDEO: input->function = MEDIA_ENT_F_CONN_SVIDEO; break; - case TVP5150_GENERATOR: - input->function = MEDIA_ENT_F_CONN_TEST; - break; } input->flags = MEDIA_ENT_FL_CONNECTOR; @@ -1431,6 +1433,11 @@ err: return ret; } +static const char * const tvp5150_test_patterns[2] = { + "Disabled", + "Black screen" +}; + static int tvp5150_probe(struct i2c_client *c, const struct i2c_device_id *id) { @@ -1488,7 +1495,7 @@ static int tvp5150_probe(struct i2c_client *c, core->norm = V4L2_STD_ALL; /* Default is autodetect */ core->input = TVP5150_COMPOSITE1; - core->enable = 1; + core->enable = true; v4l2_ctrl_handler_init(&core->hdl, 5); v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, @@ -1502,6 +1509,10 @@ static int tvp5150_probe(struct i2c_client *c, v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, V4L2_CID_PIXEL_RATE, 27000000, 27000000, 1, 27000000); + v4l2_ctrl_new_std_menu_items(&core->hdl, &tvp5150_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(tvp5150_test_patterns), + 0, 0, tvp5150_test_patterns); sd->ctrl_handler = &core->hdl; if (core->hdl.error) { res = core->hdl.error; diff --git a/include/dt-bindings/media/tvp5150.h b/include/dt-bindings/media/tvp5150.h index d30865222082..c852a35e916e 100644 --- a/include/dt-bindings/media/tvp5150.h +++ b/include/dt-bindings/media/tvp5150.h @@ -25,9 +25,8 @@ #define TVP5150_COMPOSITE0 0 #define TVP5150_COMPOSITE1 1 #define TVP5150_SVIDEO 2 -#define TVP5150_GENERATOR 3 -#define TVP5150_INPUT_NUM 4 +#define TVP5150_INPUT_NUM 3 /* TVP5150 HW outputs */ #define TVP5150_NORMAL 0 -- cgit v1.2.3 From 360104e3b8485f4923ffc202c1c2b36841de673c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Feb 2016 15:44:31 -0200 Subject: [media] media.h: get rid of MEDIA_ENT_F_CONN_TEST Defining it as a connector was a bad idea. Remove it while it is not too late. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/media-types.xml | 4 ---- drivers/media/v4l2-core/v4l2-mc.c | 1 - include/uapi/linux/media.h | 2 -- 3 files changed, 7 deletions(-) (limited to 'include') diff --git a/Documentation/DocBook/media/v4l/media-types.xml b/Documentation/DocBook/media/v4l/media-types.xml index 751c3d027103..8b4fa39cf611 100644 --- a/Documentation/DocBook/media/v4l/media-types.xml +++ b/Documentation/DocBook/media/v4l/media-types.xml @@ -56,10 +56,6 @@ MEDIA_ENT_F_CONN_COMPOSITE Connector for a RGB composite signal. - - MEDIA_ENT_F_CONN_TEST - Connector for a test generator. - MEDIA_ENT_F_CAM_SENSOR Camera video sensor entity. diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index 9d79d599d979..a7f41b323522 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -241,7 +241,6 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) break; case MEDIA_ENT_F_CONN_SVIDEO: case MEDIA_ENT_F_CONN_COMPOSITE: - case MEDIA_ENT_F_CONN_TEST: ret = media_create_pad_link(entity, 0, decoder, DEMOD_PAD_IF_INPUT, flags); diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index c9eb42a6c021..7113b1a8cb4e 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -78,8 +78,6 @@ struct media_device_info { #define MEDIA_ENT_F_CONN_RF (MEDIA_ENT_F_BASE + 21) #define MEDIA_ENT_F_CONN_SVIDEO (MEDIA_ENT_F_BASE + 22) #define MEDIA_ENT_F_CONN_COMPOSITE (MEDIA_ENT_F_BASE + 23) -/* For internal test signal generators and other debug connectors */ -#define MEDIA_ENT_F_CONN_TEST (MEDIA_ENT_F_BASE + 24) /* * I/O entities -- cgit v1.2.3 From cedc12108b55d0c571da883a4083977af612dcce Mon Sep 17 00:00:00 2001 From: Wu-Cheng Li Date: Tue, 19 Jan 2016 05:07:09 -0200 Subject: [media] v4l: add V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME Some drivers also need a control like V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE to force an encoder key frame. Add a general V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME so the new drivers and applications can use it. Signed-off-by: Wu-Cheng Li Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/controls.xml | 8 ++++++++ drivers/media/v4l2-core/v4l2-ctrls.c | 2 ++ include/uapi/linux/v4l2-controls.h | 1 + 3 files changed, 11 insertions(+) (limited to 'include') diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index 7a771492f2a5..361040e6b0f4 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -2329,6 +2329,14 @@ to search and match for the present Macroblock (MB) in the reference picture. Th vertical search range for motion estimation module in video encoder. + + + V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME  + button + Force a key frame for the next queued buffer. Applicable to encoders. +This is a general, codec-agnostic keyframe control. + + V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE  diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 130e5badd599..8b321e0aae62 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -758,6 +758,7 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE: return "Horizontal MV Search Range"; case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE: return "Vertical MV Search Range"; case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER: return "Repeat Sequence Header"; + case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: return "Force Key Frame"; /* VPX controls */ case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: return "VPX Number of Partitions"; @@ -998,6 +999,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE: *type = V4L2_CTRL_TYPE_INTEGER; break; + case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: case V4L2_CID_PAN_RESET: case V4L2_CID_TILT_RESET: case V4L2_CID_FLASH_STROBE: diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 2ae5c3ea179b..b6a357a5f053 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -390,6 +390,7 @@ enum v4l2_mpeg_video_multi_slice_mode { #define V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER (V4L2_CID_MPEG_BASE+226) #define V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE (V4L2_CID_MPEG_BASE+227) #define V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE (V4L2_CID_MPEG_BASE+228) +#define V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME (V4L2_CID_MPEG_BASE+229) #define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP (V4L2_CID_MPEG_BASE+300) #define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP (V4L2_CID_MPEG_BASE+301) -- cgit v1.2.3 From d65fae92f9a2862d73293cab6c427c40cff71f70 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Nov 2015 22:02:00 -0200 Subject: [media] v4l: Add YUV 4:2:2 and YUV 4:4:4 tri-planar non-contiguous formats The formats use three planes through the multiplanar API, allowing for non-contiguous planes in memory. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/pixfmt-yuv422m.xml | 166 +++++++++++++++++++ Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml | 177 +++++++++++++++++++++ Documentation/DocBook/media/v4l/pixfmt.xml | 2 + drivers/media/v4l2-core/v4l2-ioctl.c | 4 + include/uapi/linux/videodev2.h | 4 + 5 files changed, 353 insertions(+) create mode 100644 Documentation/DocBook/media/v4l/pixfmt-yuv422m.xml create mode 100644 Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml (limited to 'include') diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv422m.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv422m.xml new file mode 100644 index 000000000000..dd502802cb75 --- /dev/null +++ b/Documentation/DocBook/media/v4l/pixfmt-yuv422m.xml @@ -0,0 +1,166 @@ + + + V4L2_PIX_FMT_YUV422M ('YM16'), V4L2_PIX_FMT_YVU422M ('YM61') + &manvol; + + + V4L2_PIX_FMT_YUV422M + V4L2_PIX_FMT_YVU422M + Planar formats with ½ horizontal resolution, also + known as YUV and YVU 4:2:2 + + + + Description + + This is a multi-planar format, as opposed to a packed format. +The three components are separated into three sub-images or planes. + + The Y plane is first. The Y plane has one byte per pixel. +For V4L2_PIX_FMT_YUV422M the Cb data +constitutes the second plane which is half the width of the Y plane (and of the +image). Each Cb belongs to two pixels. For example, +Cb0 belongs to Y'00, +Y'01. The Cr data, just like the Cb plane, is +in the third plane. + + V4L2_PIX_FMT_YVU422M is the same except +the Cr data is stored in the second plane and the Cb data in the third plane. + + + If the Y plane has pad bytes after each row, then the Cb +and Cr planes have half as many pad bytes after their rows. In other +words, two Cx rows (including padding) is exactly as long as one Y row +(including padding). + + V4L2_PIX_FMT_YUV422M and +V4L2_PIX_FMT_YVU422M are intended to be +used only in drivers and applications that support the multi-planar API, +described in . + + + <constant>V4L2_PIX_FMT_YUV422M</constant> 4 × 4 +pixel image + + + Byte Order. + Each cell is one byte. + + + + + + start0 + 0: + Y'00 + Y'01 + Y'02 + Y'03 + + + start0 + 4: + Y'10 + Y'11 + Y'12 + Y'13 + + + start0 + 8: + Y'20 + Y'21 + Y'22 + Y'23 + + + start0 + 12: + Y'30 + Y'31 + Y'32 + Y'33 + + + + start1 + 0: + Cb00 + Cb01 + + + start1 + 2: + Cb10 + Cb11 + + + start1 + 4: + Cb20 + Cb21 + + + start1 + 6: + Cb30 + Cb31 + + + + start2 + 0: + Cr00 + Cr01 + + + start2 + 2: + Cr10 + Cr11 + + + start2 + 4: + Cr20 + Cr21 + + + start2 + 6: + Cr30 + Cr31 + + + + + + + + + Color Sample Location. + + + + + + + 01 + 23 + + + 0 + YCY + YCY + + + 1 + YCY + YCY + + + 2 + YCY + YCY + + + 3 + YCY + YCY + + + + + + + + + diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml new file mode 100644 index 000000000000..1b7335940bc7 --- /dev/null +++ b/Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml @@ -0,0 +1,177 @@ + + + V4L2_PIX_FMT_YUV444M ('YM24'), V4L2_PIX_FMT_YVU444M ('YM42') + &manvol; + + + V4L2_PIX_FMT_YUV444M + V4L2_PIX_FMT_YVU444M + Planar formats with full horizontal resolution, also + known as YUV and YVU 4:4:4 + + + + Description + + This is a multi-planar format, as opposed to a packed format. +The three components are separated into three sub-images or planes. + + The Y plane is first. The Y plane has one byte per pixel. +For V4L2_PIX_FMT_YUV444M the Cb data +constitutes the second plane which is the same width and height as the Y plane +(and as the image). The Cr data, just like the Cb plane, is in the third plane. + + + V4L2_PIX_FMT_YVU444M is the same except +the Cr data is stored in the second plane and the Cb data in the third plane. + + If the Y plane has pad bytes after each row, then the Cb +and Cr planes have the same number of pad bytes after their rows. + + V4L2_PIX_FMT_YUV444M and +V4L2_PIX_FMT_YUV444M are intended to be +used only in drivers and applications that support the multi-planar API, +described in . + + + <constant>V4L2_PIX_FMT_YUV444M</constant> 4 × 4 +pixel image + + + Byte Order. + Each cell is one byte. + + + + + + start0 + 0: + Y'00 + Y'01 + Y'02 + Y'03 + + + start0 + 4: + Y'10 + Y'11 + Y'12 + Y'13 + + + start0 + 8: + Y'20 + Y'21 + Y'22 + Y'23 + + + start0 + 12: + Y'30 + Y'31 + Y'32 + Y'33 + + + + start1 + 0: + Cb00 + Cb01 + Cb02 + Cb03 + + + start1 + 4: + Cb10 + Cb11 + Cb12 + Cb13 + + + start1 + 8: + Cb20 + Cb21 + Cb22 + Cb23 + + + start1 + 12: + Cb20 + Cb21 + Cb32 + Cb33 + + + + start2 + 0: + Cr00 + Cr01 + Cr02 + Cr03 + + + start2 + 4: + Cr10 + Cr11 + Cr12 + Cr13 + + + start2 + 8: + Cr20 + Cr21 + Cr22 + Cr23 + + + start2 + 12: + Cr30 + Cr31 + Cr32 + Cr33 + + + + + + + + + Color Sample Location. + + + + + + + 01 + 23 + + + 0 + YCYC + YCYC + + + 1 + YCYC + YCYC + + + 2 + YCYC + YCYC + + + 3 + YCYC + YCYC + + + + + + + + + diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml index 9e77ff353feb..2f02f9441443 100644 --- a/Documentation/DocBook/media/v4l/pixfmt.xml +++ b/Documentation/DocBook/media/v4l/pixfmt.xml @@ -1628,6 +1628,8 @@ information. &sub-y41p; &sub-yuv420; &sub-yuv420m; + &sub-yuv422m; + &sub-yuv444m; &sub-yuv410; &sub-yuv422p; &sub-yuv411p; diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 8a018c6dd16a..14843090fd61 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1191,6 +1191,10 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_NV12MT_16X16: descr = "Y/CbCr 4:2:0 (16x16 MB, N-C)"; break; case V4L2_PIX_FMT_YUV420M: descr = "Planar YUV 4:2:0 (N-C)"; break; case V4L2_PIX_FMT_YVU420M: descr = "Planar YVU 4:2:0 (N-C)"; break; + case V4L2_PIX_FMT_YUV422M: descr = "Planar YUV 4:2:2 (N-C)"; break; + case V4L2_PIX_FMT_YVU422M: descr = "Planar YVU 4:2:2 (N-C)"; break; + case V4L2_PIX_FMT_YUV444M: descr = "Planar YUV 4:4:4 (N-C)"; break; + case V4L2_PIX_FMT_YVU444M: descr = "Planar YVU 4:4:4 (N-C)"; break; case V4L2_PIX_FMT_SBGGR8: descr = "8-bit Bayer BGBG/GRGR"; break; case V4L2_PIX_FMT_SGBRG8: descr = "8-bit Bayer GBGB/RGRG"; break; case V4L2_PIX_FMT_SGRBG8: descr = "8-bit Bayer GRGR/BGBG"; break; diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 14cd5ebfee6d..466458422385 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -546,6 +546,10 @@ struct v4l2_pix_format { /* three non contiguous planes - Y, Cb, Cr */ #define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'M', '1', '2') /* 12 YUV420 planar */ #define V4L2_PIX_FMT_YVU420M v4l2_fourcc('Y', 'M', '2', '1') /* 12 YVU420 planar */ +#define V4L2_PIX_FMT_YUV422M v4l2_fourcc('Y', 'M', '1', '6') /* 16 YUV422 planar */ +#define V4L2_PIX_FMT_YVU422M v4l2_fourcc('Y', 'M', '6', '1') /* 16 YVU422 planar */ +#define V4L2_PIX_FMT_YUV444M v4l2_fourcc('Y', 'M', '2', '4') /* 24 YUV444 planar */ +#define V4L2_PIX_FMT_YVU444M v4l2_fourcc('Y', 'M', '4', '2') /* 24 YVU444 planar */ /* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */ #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */ -- cgit v1.2.3 From f3af9572e85447102202c644c50c7460009d1cae Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 Aug 2015 18:37:01 -0300 Subject: [media] v4l: vsp1: Add VSP+DU support Implement internal control of the VSP pipeline to be used by the DU DRM/KMS driver when using the VSP as an internal composer handled through DRM/KMS only. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/Makefile | 2 +- drivers/media/platform/vsp1/vsp1.h | 3 +- drivers/media/platform/vsp1/vsp1_drm.c | 552 +++++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_drm.h | 26 ++ drivers/media/platform/vsp1/vsp1_drv.c | 23 +- include/media/vsp1.h | 30 ++ 6 files changed, 625 insertions(+), 11 deletions(-) create mode 100644 drivers/media/platform/vsp1/vsp1_drm.c create mode 100644 drivers/media/platform/vsp1/vsp1_drm.h create mode 100644 include/media/vsp1.h (limited to 'include') diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile index 0ef0b5384125..447e72a2ef43 100644 --- a/drivers/media/platform/vsp1/Makefile +++ b/drivers/media/platform/vsp1/Makefile @@ -1,5 +1,5 @@ vsp1-y := vsp1_drv.o vsp1_entity.o vsp1_pipe.o -vsp1-y += vsp1_video.o +vsp1-y += vsp1_drm.o vsp1_video.o vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o vsp1-y += vsp1_hsit.o vsp1_lif.o vsp1_lut.o vsp1-y += vsp1_bru.o vsp1_sru.o vsp1_uds.o diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 454201bf59ee..67a026ae88cb 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -26,6 +26,7 @@ struct clk; struct device; +struct vsp1_drm; struct vsp1_platform_data; struct vsp1_bru; struct vsp1_hsit; @@ -78,8 +79,8 @@ struct vsp1_device { struct v4l2_device v4l2_dev; struct media_device media_dev; - struct media_entity_operations media_ops; + struct vsp1_drm *drm; }; int vsp1_device_get(struct vsp1_device *vsp1); diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c new file mode 100644 index 000000000000..ac81ff10c339 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -0,0 +1,552 @@ +/* + * vsp1_drm.c -- R-Car VSP1 DRM API + * + * Copyright (C) 2015 Renesas Electronics Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include + +#include +#include + +#include "vsp1.h" +#include "vsp1_bru.h" +#include "vsp1_drm.h" +#include "vsp1_lif.h" +#include "vsp1_pipe.h" +#include "vsp1_rwpf.h" + +/* ----------------------------------------------------------------------------- + * Runtime Handling + */ + +static int vsp1_drm_pipeline_run(struct vsp1_pipeline *pipe) +{ + struct vsp1_device *vsp1 = pipe->output->entity.vsp1; + int ret; + + if (vsp1->drm->update) { + struct vsp1_entity *entity; + + list_for_each_entry(entity, &pipe->entities, list_pipe) { + /* Skip unused RPFs. */ + if (entity->type == VSP1_ENTITY_RPF) { + struct vsp1_rwpf *rpf = + to_rwpf(&entity->subdev); + + if (!pipe->inputs[rpf->entity.index]) + continue; + } + + vsp1_entity_route_setup(entity); + + ret = v4l2_subdev_call(&entity->subdev, video, + s_stream, 1); + if (ret < 0) { + dev_err(vsp1->dev, + "DRM pipeline start failure on entity %s\n", + entity->subdev.name); + return ret; + } + } + + vsp1->drm->update = false; + } + + vsp1_pipeline_run(pipe); + + return 0; +} + +static void vsp1_drm_pipeline_frame_end(struct vsp1_pipeline *pipe) +{ + unsigned long flags; + + spin_lock_irqsave(&pipe->irqlock, flags); + if (pipe->num_inputs) + vsp1_drm_pipeline_run(pipe); + spin_unlock_irqrestore(&pipe->irqlock, flags); +} + +/* ----------------------------------------------------------------------------- + * DU Driver API + */ + +int vsp1_du_init(struct device *dev) +{ + struct vsp1_device *vsp1 = dev_get_drvdata(dev); + + if (!vsp1) + return -EPROBE_DEFER; + + return 0; +} +EXPORT_SYMBOL_GPL(vsp1_du_init); + +/** + * vsp1_du_setup_lif - Setup the output part of the VSP pipeline + * @dev: the VSP device + * @width: output frame width in pixels + * @height: output frame height in pixels + * + * Configure the output part of VSP DRM pipeline for the given frame @width and + * @height. This sets up formats on the BRU source pad, the WPF0 sink and source + * pads, and the LIF sink pad. + * + * As the media bus code on the BRU source pad is conditioned by the + * configuration of the BRU sink 0 pad, we also set up the formats on all BRU + * sinks, even if the configuration will be overwritten later by + * vsp1_du_setup_rpf(). This ensures that the BRU configuration is set to a well + * defined state. + * + * Return 0 on success or a negative error code on failure. + */ +int vsp1_du_setup_lif(struct device *dev, unsigned int width, + unsigned int height) +{ + struct vsp1_device *vsp1 = dev_get_drvdata(dev); + struct vsp1_pipeline *pipe = &vsp1->drm->pipe; + struct vsp1_bru *bru = vsp1->bru; + struct v4l2_subdev_format format; + unsigned int i; + int ret; + + dev_dbg(vsp1->dev, "%s: configuring LIF with format %ux%u\n", + __func__, width, height); + + if (width == 0 || height == 0) { + /* Zero width or height means the CRTC is being disabled, stop + * the pipeline and turn the light off. + */ + ret = vsp1_pipeline_stop(pipe); + if (ret == -ETIMEDOUT) + dev_err(vsp1->dev, "DRM pipeline stop timeout\n"); + + media_entity_pipeline_stop(&pipe->output->entity.subdev.entity); + + for (i = 0; i < bru->entity.source_pad; ++i) { + bru->inputs[i].rpf = NULL; + pipe->inputs[i] = NULL; + } + + pipe->num_inputs = 0; + + vsp1_device_put(vsp1); + + dev_dbg(vsp1->dev, "%s: pipeline disabled\n", __func__); + + return 0; + } + + /* Configure the format at the BRU sinks and propagate it through the + * pipeline. + */ + memset(&format, 0, sizeof(format)); + format.which = V4L2_SUBDEV_FORMAT_ACTIVE; + + for (i = 0; i < bru->entity.source_pad; ++i) { + format.pad = i; + + format.format.width = width; + format.format.height = height; + format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; + format.format.field = V4L2_FIELD_NONE; + + ret = v4l2_subdev_call(&bru->entity.subdev, pad, + set_fmt, NULL, &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on BRU pad %u\n", + __func__, format.format.width, format.format.height, + format.format.code, i); + } + + format.pad = bru->entity.source_pad; + format.format.width = width; + format.format.height = height; + format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; + format.format.field = V4L2_FIELD_NONE; + + ret = v4l2_subdev_call(&bru->entity.subdev, pad, set_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on BRU pad %u\n", + __func__, format.format.width, format.format.height, + format.format.code, i); + + format.pad = RWPF_PAD_SINK; + ret = v4l2_subdev_call(&vsp1->wpf[0]->entity.subdev, pad, set_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF0 sink\n", + __func__, format.format.width, format.format.height, + format.format.code); + + format.pad = RWPF_PAD_SOURCE; + ret = v4l2_subdev_call(&vsp1->wpf[0]->entity.subdev, pad, get_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF0 source\n", + __func__, format.format.width, format.format.height, + format.format.code); + + format.pad = LIF_PAD_SINK; + ret = v4l2_subdev_call(&vsp1->lif->entity.subdev, pad, set_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF sink\n", + __func__, format.format.width, format.format.height, + format.format.code); + + /* Verify that the format at the output of the pipeline matches the + * requested frame size and media bus code. + */ + if (format.format.width != width || format.format.height != height || + format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) { + dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__); + return -EPIPE; + } + + /* Mark the pipeline as streaming and enable the VSP1. This will store + * the pipeline pointer in all entities, which the s_stream handlers + * will need. We don't start the entities themselves right at this point + * as there's no plane configured yet, so we can't start processing + * buffers. + */ + ret = vsp1_device_get(vsp1); + if (ret < 0) + return ret; + + ret = media_entity_pipeline_start(&pipe->output->entity.subdev.entity, + &pipe->pipe); + if (ret < 0) { + dev_dbg(vsp1->dev, "%s: pipeline start failed\n", __func__); + vsp1_device_put(vsp1); + return ret; + } + + dev_dbg(vsp1->dev, "%s: pipeline enabled\n", __func__); + + return 0; +} +EXPORT_SYMBOL_GPL(vsp1_du_setup_lif); + +/** + * vsp1_du_setup_rpf - Setup one RPF input of the VSP pipeline + * @dev: the VSP device + * @rpf_index: index of the RPF to setup (0-based) + * @pixelformat: V4L2 pixel format for the RPF memory input + * @pitch: number of bytes per line in the image stored in memory + * @mem: DMA addresses of the memory buffers (one per plane) + * @src: the source crop rectangle for the RPF + * @dst: the destination compose rectangle for the BRU input + * + * Configure the VSP to perform composition of the image referenced by @mem + * through RPF @rpf_index, using the @src crop rectangle and the @dst + * composition rectangle. The Z-order is fixed with RPF 0 at the bottom. + * + * Image format as stored in memory is expressed as a V4L2 @pixelformat value. + * As a special case, setting the pixel format to 0 will disable the RPF. The + * @pitch, @mem, @src and @dst parameters are ignored in that case. Calling the + * function on a disabled RPF is allowed. + * + * The memory pitch is configurable to allow for padding at end of lines, or + * simple for images that extend beyond the crop rectangle boundaries. The + * @pitch value is expressed in bytes and applies to all planes for multiplanar + * formats. + * + * The source memory buffer is referenced by the DMA address of its planes in + * the @mem array. Up to two planes are supported. The second plane DMA address + * is ignored for formats using a single plane. + * + * This function isn't reentrant, the caller needs to serialize calls. + * + * TODO: Implement Z-order control by decoupling the RPF index from the BRU + * input index. + * + * Return 0 on success or a negative error code on failure. + */ +int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index, + u32 pixelformat, unsigned int pitch, + dma_addr_t mem[2], const struct v4l2_rect *src, + const struct v4l2_rect *dst) +{ + struct vsp1_device *vsp1 = dev_get_drvdata(dev); + struct vsp1_pipeline *pipe = &vsp1->drm->pipe; + const struct vsp1_format_info *fmtinfo; + struct v4l2_subdev_selection sel; + struct v4l2_subdev_format format; + struct vsp1_rwpf_memory memory; + struct vsp1_rwpf *rpf; + unsigned long flags; + bool start_stop = false; + int ret; + + if (rpf_index >= vsp1->pdata.rpf_count) + return -EINVAL; + + rpf = vsp1->rpf[rpf_index]; + + if (pixelformat == 0) { + dev_dbg(vsp1->dev, "%s: RPF%u: disable requested\n", __func__, + rpf_index); + + spin_lock_irqsave(&pipe->irqlock, flags); + + if (pipe->inputs[rpf_index]) { + /* Remove the RPF from the pipeline if it was previously + * enabled. + */ + vsp1->bru->inputs[rpf_index].rpf = NULL; + pipe->inputs[rpf_index] = NULL; + + vsp1->drm->update = true; + start_stop = --pipe->num_inputs == 0; + } + + spin_unlock_irqrestore(&pipe->irqlock, flags); + + /* Stop the pipeline if we're the last user. */ + if (start_stop) + vsp1_pipeline_stop(pipe); + + return 0; + } + + dev_dbg(vsp1->dev, + "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad }\n", + __func__, rpf_index, + src->left, src->top, src->width, src->height, + dst->left, dst->top, dst->width, dst->height, + pixelformat, pitch, &mem[0], &mem[1]); + + /* Set the stride at the RPF input. */ + fmtinfo = vsp1_get_format_info(pixelformat); + if (!fmtinfo) { + dev_dbg(vsp1->dev, "Unsupport pixel format %08x for RPF\n", + pixelformat); + return -EINVAL; + } + + rpf->fmtinfo = fmtinfo; + rpf->format.num_planes = fmtinfo->planes; + rpf->format.plane_fmt[0].bytesperline = pitch; + rpf->format.plane_fmt[1].bytesperline = pitch; + + /* Configure the format on the RPF sink pad and propagate it up to the + * BRU sink pad. + */ + memset(&format, 0, sizeof(format)); + format.which = V4L2_SUBDEV_FORMAT_ACTIVE; + format.pad = RWPF_PAD_SINK; + format.format.width = src->width + src->left; + format.format.height = src->height + src->top; + format.format.code = fmtinfo->mbus; + format.format.field = V4L2_FIELD_NONE; + + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, + "%s: set format %ux%u (%x) on RPF%u sink\n", + __func__, format.format.width, format.format.height, + format.format.code, rpf->entity.index); + + memset(&sel, 0, sizeof(sel)); + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sel.pad = RWPF_PAD_SINK; + sel.target = V4L2_SEL_TGT_CROP; + sel.r = *src; + + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_selection, NULL, + &sel); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, + "%s: set selection (%u,%u)/%ux%u on RPF%u sink\n", + __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height, + rpf->entity.index); + + /* RPF source, hardcode the format to ARGB8888 to turn on format + * conversion if needed. + */ + format.pad = RWPF_PAD_SOURCE; + + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, get_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, + "%s: got format %ux%u (%x) on RPF%u source\n", + __func__, format.format.width, format.format.height, + format.format.code, rpf->entity.index); + + format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; + + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, + &format); + if (ret < 0) + return ret; + + /* BRU sink, propagate the format from the RPF source. */ + format.pad = rpf->entity.index; + + ret = v4l2_subdev_call(&vsp1->bru->entity.subdev, pad, set_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on BRU pad %u\n", + __func__, format.format.width, format.format.height, + format.format.code, format.pad); + + sel.pad = rpf->entity.index; + sel.target = V4L2_SEL_TGT_COMPOSE; + sel.r = *dst; + + ret = v4l2_subdev_call(&vsp1->bru->entity.subdev, pad, set_selection, + NULL, &sel); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, + "%s: set selection (%u,%u)/%ux%u on BRU pad %u\n", + __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height, + sel.pad); + + /* Store the compose rectangle coordinates in the RPF. */ + rpf->location.left = dst->left; + rpf->location.top = dst->top; + + /* Set the memory buffer address. */ + memory.num_planes = fmtinfo->planes; + memory.addr[0] = mem[0]; + memory.addr[1] = mem[1]; + + rpf->ops->set_memory(rpf, &memory); + + spin_lock_irqsave(&pipe->irqlock, flags); + + /* If the RPF was previously stopped set the BRU input to the RPF and + * store the RPF in the pipeline inputs array. + */ + if (!pipe->inputs[rpf->entity.index]) { + vsp1->bru->inputs[rpf_index].rpf = rpf; + pipe->inputs[rpf->entity.index] = rpf; + start_stop = pipe->num_inputs++ == 0; + } + + /* Start the pipeline if it's currently stopped. */ + vsp1->drm->update = true; + if (start_stop) + vsp1_drm_pipeline_run(pipe); + + spin_unlock_irqrestore(&pipe->irqlock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(vsp1_du_setup_rpf); + +/* ----------------------------------------------------------------------------- + * Initialization + */ + +int vsp1_drm_create_links(struct vsp1_device *vsp1) +{ + const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE; + unsigned int i; + int ret; + + /* VSPD instances require a BRU to perform composition and a LIF to + * output to the DU. + */ + if (!vsp1->bru || !vsp1->lif) + return -ENXIO; + + for (i = 0; i < vsp1->pdata.rpf_count; ++i) { + struct vsp1_rwpf *rpf = vsp1->rpf[i]; + + ret = media_create_pad_link(&rpf->entity.subdev.entity, + RWPF_PAD_SOURCE, + &vsp1->bru->entity.subdev.entity, + i, flags); + if (ret < 0) + return ret; + + rpf->entity.sink = &vsp1->bru->entity.subdev.entity; + rpf->entity.sink_pad = i; + } + + ret = media_create_pad_link(&vsp1->bru->entity.subdev.entity, + vsp1->bru->entity.source_pad, + &vsp1->wpf[0]->entity.subdev.entity, + RWPF_PAD_SINK, flags); + if (ret < 0) + return ret; + + vsp1->bru->entity.sink = &vsp1->wpf[0]->entity.subdev.entity; + vsp1->bru->entity.sink_pad = RWPF_PAD_SINK; + + ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity, + RWPF_PAD_SOURCE, + &vsp1->lif->entity.subdev.entity, + LIF_PAD_SINK, flags); + if (ret < 0) + return ret; + + return 0; +} + +int vsp1_drm_init(struct vsp1_device *vsp1) +{ + struct vsp1_pipeline *pipe; + unsigned int i; + + vsp1->drm = devm_kzalloc(vsp1->dev, sizeof(*vsp1->drm), GFP_KERNEL); + if (!vsp1->drm) + return -ENOMEM; + + pipe = &vsp1->drm->pipe; + + vsp1_pipeline_init(pipe); + pipe->frame_end = vsp1_drm_pipeline_frame_end; + + /* The DRM pipeline is static, add entities manually. */ + for (i = 0; i < vsp1->pdata.rpf_count; ++i) { + struct vsp1_rwpf *input = vsp1->rpf[i]; + + list_add_tail(&input->entity.list_pipe, &pipe->entities); + } + + list_add_tail(&vsp1->bru->entity.list_pipe, &pipe->entities); + list_add_tail(&vsp1->wpf[0]->entity.list_pipe, &pipe->entities); + list_add_tail(&vsp1->lif->entity.list_pipe, &pipe->entities); + + pipe->bru = &vsp1->bru->entity; + pipe->lif = &vsp1->lif->entity; + pipe->output = vsp1->wpf[0]; + + return 0; +} diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h new file mode 100644 index 000000000000..2ad320ab1e45 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -0,0 +1,26 @@ +/* + * vsp1_drm.h -- R-Car VSP1 DRM/KMS Interface + * + * Copyright (C) 2015 Renesas Electronics Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#ifndef __VSP1_DRM_H__ +#define __VSP1_DRM_H__ + +#include "vsp1_pipe.h" + +struct vsp1_drm { + struct vsp1_pipeline pipe; + bool update; +}; + +int vsp1_drm_init(struct vsp1_device *vsp1); +int vsp1_drm_create_links(struct vsp1_device *vsp1); + +#endif /* __VSP1_DRM_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 1e10fc4723c5..74b5920e516b 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -25,6 +25,7 @@ #include "vsp1.h" #include "vsp1_bru.h" +#include "vsp1_drm.h" #include "vsp1_hsit.h" #include "vsp1_lif.h" #include "vsp1_lut.h" @@ -120,7 +121,7 @@ static int vsp1_create_sink_links(struct vsp1_device *vsp1, return 0; } -static int vsp1_create_links(struct vsp1_device *vsp1) +static int vsp1_uapi_create_links(struct vsp1_device *vsp1) { struct vsp1_entity *entity; unsigned int i; @@ -145,9 +146,6 @@ static int vsp1_create_links(struct vsp1_device *vsp1) return ret; } - if (!vsp1->pdata.uapi) - return 0; - for (i = 0; i < vsp1->pdata.rpf_count; ++i) { struct vsp1_rwpf *rpf = vsp1->rpf[i]; @@ -360,15 +358,22 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) } /* Create links. */ - ret = vsp1_create_links(vsp1); + if (vsp1->pdata.uapi) + ret = vsp1_uapi_create_links(vsp1); + else + ret = vsp1_drm_create_links(vsp1); if (ret < 0) goto done; - if (vsp1->pdata.uapi) { + /* Register subdev nodes if the userspace API is enabled or initialize + * the DRM pipeline otherwise. + */ + if (vsp1->pdata.uapi) ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev); - if (ret < 0) - goto done; - } + else + ret = vsp1_drm_init(vsp1); + if (ret < 0) + goto done; ret = media_device_register(mdev); diff --git a/include/media/vsp1.h b/include/media/vsp1.h new file mode 100644 index 000000000000..2c1aea7066be --- /dev/null +++ b/include/media/vsp1.h @@ -0,0 +1,30 @@ +/* + * vsp1.h -- R-Car VSP1 API + * + * Copyright (C) 2015 Renesas Electronics Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#ifndef __MEDIA_VSP1_H__ +#define __MEDIA_VSP1_H__ + +#include + +struct device; +struct v4l2_rect; + +int vsp1_du_init(struct device *dev); + +int vsp1_du_setup_lif(struct device *dev, unsigned int width, + unsigned int height); + +int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf, u32 pixelformat, + unsigned int pitch, dma_addr_t mem[2], + const struct v4l2_rect *src, const struct v4l2_rect *dst); + +#endif /* __MEDIA_VSP1_H__ */ -- cgit v1.2.3 From 7b4baddca69e61cdbabe8caff614778d188d89d8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 10 Sep 2015 09:28:39 -0300 Subject: [media] v4l: vsp1: Implement atomic update for the DRM driver Add two API functions named vsp1_du_atomic_begin() and vsp1_du_atomic_flush() to signal the start and end of an atomic update. The vsp1_du_setup_rpf() function is renamed to vsp1_du_atomic_update() for consistency. With this new API, the driver will reprogram all modified inputs atomically before restarting the video stream. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drm.c | 70 +++++++++++++++++++++++++--------- drivers/media/platform/vsp1/vsp1_drm.h | 7 ++++ include/media/vsp1.h | 9 +++-- 3 files changed, 66 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index a918bb4ab46c..8c76086caa67 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -254,7 +254,26 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width, EXPORT_SYMBOL_GPL(vsp1_du_setup_lif); /** - * vsp1_du_setup_rpf - Setup one RPF input of the VSP pipeline + * vsp1_du_atomic_begin - Prepare for an atomic update + * @dev: the VSP device + */ +void vsp1_du_atomic_begin(struct device *dev) +{ + struct vsp1_device *vsp1 = dev_get_drvdata(dev); + struct vsp1_pipeline *pipe = &vsp1->drm->pipe; + unsigned long flags; + + spin_lock_irqsave(&pipe->irqlock, flags); + + vsp1->drm->num_inputs = pipe->num_inputs; + vsp1->drm->update = false; + + spin_unlock_irqrestore(&pipe->irqlock, flags); +} +EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin); + +/** + * vsp1_du_atomic_update - Setup one RPF input of the VSP pipeline * @dev: the VSP device * @rpf_index: index of the RPF to setup (0-based) * @pixelformat: V4L2 pixel format for the RPF memory input @@ -288,10 +307,10 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif); * * Return 0 on success or a negative error code on failure. */ -int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index, - u32 pixelformat, unsigned int pitch, - dma_addr_t mem[2], const struct v4l2_rect *src, - const struct v4l2_rect *dst) +int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, + u32 pixelformat, unsigned int pitch, + dma_addr_t mem[2], const struct v4l2_rect *src, + const struct v4l2_rect *dst) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); struct vsp1_pipeline *pipe = &vsp1->drm->pipe; @@ -301,7 +320,6 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index, struct vsp1_rwpf_memory memory; struct vsp1_rwpf *rpf; unsigned long flags; - bool start_stop = false; int ret; if (rpf_index >= vsp1->pdata.rpf_count) @@ -322,16 +340,11 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index, vsp1->bru->inputs[rpf_index].rpf = NULL; pipe->inputs[rpf_index] = NULL; - vsp1->drm->update = true; - start_stop = --pipe->num_inputs == 0; + pipe->num_inputs--; } spin_unlock_irqrestore(&pipe->irqlock, flags); - /* Stop the pipeline if we're the last user. */ - if (start_stop) - vsp1_pipeline_stop(pipe); - return 0; } @@ -459,19 +472,42 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index, if (!pipe->inputs[rpf->entity.index]) { vsp1->bru->inputs[rpf_index].rpf = rpf; pipe->inputs[rpf->entity.index] = rpf; - start_stop = pipe->num_inputs++ == 0; + pipe->num_inputs++; } - /* Start the pipeline if it's currently stopped. */ + spin_unlock_irqrestore(&pipe->irqlock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(vsp1_du_atomic_update); + +/** + * vsp1_du_atomic_flush - Commit an atomic update + * @dev: the VSP device + */ +void vsp1_du_atomic_flush(struct device *dev) +{ + struct vsp1_device *vsp1 = dev_get_drvdata(dev); + struct vsp1_pipeline *pipe = &vsp1->drm->pipe; + unsigned long flags; + bool stop = false; + + spin_lock_irqsave(&pipe->irqlock, flags); + vsp1->drm->update = true; - if (start_stop) + + /* Start or stop the pipeline if needed. */ + if (!vsp1->drm->num_inputs && pipe->num_inputs) vsp1_drm_pipeline_run(pipe); + else if (vsp1->drm->num_inputs && !pipe->num_inputs) + stop = true; spin_unlock_irqrestore(&pipe->irqlock, flags); - return 0; + if (stop) + vsp1_pipeline_stop(pipe); } -EXPORT_SYMBOL_GPL(vsp1_du_setup_rpf); +EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush); /* ----------------------------------------------------------------------------- * Initialization diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index 2ad320ab1e45..25d7f017feb4 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -15,8 +15,15 @@ #include "vsp1_pipe.h" +/** + * vsp1_drm - State for the API exposed to the DRM driver + * @pipe: the VSP1 pipeline used for display + * @num_inputs: number of active pipeline inputs at the beginning of an update + * @update: the pipeline configuration has been updated + */ struct vsp1_drm { struct vsp1_pipeline pipe; + unsigned int num_inputs; bool update; }; diff --git a/include/media/vsp1.h b/include/media/vsp1.h index 2c1aea7066be..cc541753896f 100644 --- a/include/media/vsp1.h +++ b/include/media/vsp1.h @@ -23,8 +23,11 @@ int vsp1_du_init(struct device *dev); int vsp1_du_setup_lif(struct device *dev, unsigned int width, unsigned int height); -int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf, u32 pixelformat, - unsigned int pitch, dma_addr_t mem[2], - const struct v4l2_rect *src, const struct v4l2_rect *dst); +int vsp1_du_atomic_begin(struct device *dev); +int vsp1_du_atomic_update(struct device *dev, unsigned int rpf, u32 pixelformat, + unsigned int pitch, dma_addr_t mem[2], + const struct v4l2_rect *src, + const struct v4l2_rect *dst); +int vsp1_du_atomic_flush(struct device *dev); #endif /* __MEDIA_VSP1_H__ */ -- cgit v1.2.3 From 41b44e35ba9b34e50a65c05ecf7642c07bd3e8aa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Feb 2016 11:42:04 -0300 Subject: [media] media-device: move PCI/USB helper functions from v4l2-mc Those ancillary functions could be called even when compiled without V4L2 support, as warned by ktest build robot: All errors (new ones prefixed by >>): >> ERROR: "__v4l2_mc_usb_media_device_init" [drivers/media/usb/dvb-usb/dvb-usb.ko] undefined! >> ERROR: "__v4l2_mc_usb_media_device_init" [drivers/media/usb/dvb-usb-v2/dvb_usb_v2.ko] undefined! >> ERROR: "__v4l2_mc_usb_media_device_init" [drivers/media/usb/au0828/au0828.ko] undefined! Also, there's nothing there that are specific to V4L2. So, move those ancillary functions to MC core. No functional changes. Just function rename. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-device.c | 74 ++++++++++++++++++++++++++++ drivers/media/pci/saa7134/saa7134-core.c | 2 +- drivers/media/usb/au0828/au0828-core.c | 4 +- drivers/media/usb/cx231xx/cx231xx-cards.c | 2 +- drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 4 +- drivers/media/usb/dvb-usb/dvb-usb-dvb.c | 4 +- drivers/media/usb/em28xx/em28xx-cards.c | 6 +-- drivers/media/usb/siano/smsusb.c | 4 +- drivers/media/v4l2-core/v4l2-mc.c | 76 +---------------------------- include/media/media-device.h | 53 ++++++++++++++++++++ include/media/v4l2-mc.h | 46 ----------------- 11 files changed, 141 insertions(+), 134 deletions(-) (limited to 'include') diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 5ebb3cd31345..fe376b6b5244 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include @@ -753,4 +755,76 @@ struct media_device *media_device_find_devres(struct device *dev) } EXPORT_SYMBOL_GPL(media_device_find_devres); +struct media_device *media_device_pci_init(struct pci_dev *pci_dev, + const char *name) +{ +#ifdef CONFIG_PCI + struct media_device *mdev; + + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return NULL; + + mdev->dev = &pci_dev->dev; + + if (name) + strlcpy(mdev->model, name, sizeof(mdev->model)); + else + strlcpy(mdev->model, pci_name(pci_dev), sizeof(mdev->model)); + + sprintf(mdev->bus_info, "PCI:%s", pci_name(pci_dev)); + + mdev->hw_revision = (pci_dev->subsystem_vendor << 16) + | pci_dev->subsystem_device; + + mdev->driver_version = LINUX_VERSION_CODE; + + media_device_init(mdev); + + return mdev; +#else + return NULL; +#endif +} +EXPORT_SYMBOL_GPL(media_device_pci_init); + +struct media_device *__media_device_usb_init(struct usb_device *udev, + const char *board_name, + const char *driver_name) +{ +#ifdef CONFIG_USB + struct media_device *mdev; + + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return NULL; + + mdev->dev = &udev->dev; + + if (driver_name) + strlcpy(mdev->driver_name, driver_name, + sizeof(mdev->driver_name)); + + if (board_name) + strlcpy(mdev->model, board_name, sizeof(mdev->model)); + else if (udev->product) + strlcpy(mdev->model, udev->product, sizeof(mdev->model)); + else + strlcpy(mdev->model, "unknown model", sizeof(mdev->model)); + if (udev->serial) + strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); + usb_make_path(udev, mdev->bus_info, sizeof(mdev->bus_info)); + mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); + mdev->driver_version = LINUX_VERSION_CODE; + + media_device_init(mdev); + + return mdev; +#else + return NULL; +#endif +} +EXPORT_SYMBOL_GPL(__media_device_usb_init); + + #endif /* CONFIG_MEDIA_CONTROLLER */ diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c index 8f3ba4077130..8ae65bb320a3 100644 --- a/drivers/media/pci/saa7134/saa7134-core.c +++ b/drivers/media/pci/saa7134/saa7134-core.c @@ -1043,7 +1043,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev, sprintf(dev->name, "saa%x[%d]", pci_dev->device, dev->nr); #ifdef CONFIG_MEDIA_CONTROLLER - dev->media_dev = v4l2_mc_pci_media_device_init(pci_dev, dev->name); + dev->media_dev = media_device_pci_init(pci_dev, dev->name); if (!dev->media_dev) { err = -ENOMEM; goto fail0; diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index 7cafe4dd5fd1..cfcd08ec388f 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -192,9 +192,9 @@ static int au0828_media_device_init(struct au0828_dev *dev, struct media_device *mdev; if (!dev->board.name) - mdev = v4l2_mc_usb_media_device_init(udev, "unknown au0828"); + mdev = media_device_usb_init(udev, "unknown au0828"); else - mdev = v4l2_mc_usb_media_device_init(udev, dev->board.name); + mdev = media_device_usb_init(udev, dev->board.name); if (!mdev) return -ENOMEM; diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 9e3a5d2038c2..29bd7536feed 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1212,7 +1212,7 @@ static int cx231xx_media_device_init(struct cx231xx *dev, #ifdef CONFIG_MEDIA_CONTROLLER struct media_device *mdev; - mdev = v4l2_mc_usb_media_device_init(udev, dev->board.name); + mdev = media_device_usb_init(udev, dev->board.name); if (!mdev) return -ENOMEM; diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index 4a8769781cea..58250250a443 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -20,7 +20,7 @@ */ #include "dvb_usb_common.h" -#include +#include static int dvb_usbv2_disable_rc_polling; module_param_named(disable_rc_polling, dvb_usbv2_disable_rc_polling, int, 0644); @@ -408,7 +408,7 @@ static int dvb_usbv2_media_device_init(struct dvb_usb_adapter *adap) struct dvb_usb_device *d = adap_to_d(adap); struct usb_device *udev = d->udev; - mdev = v4l2_mc_usb_media_device_init(udev, d->name); + mdev = media_device_usb_init(udev, d->name); if (!mdev) return -ENOMEM; diff --git a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c index 513b0c14e4f0..7509408b0b8e 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c @@ -7,7 +7,7 @@ * linux-dvb API. */ #include "dvb-usb-common.h" -#include +#include /* does the complete input transfer handling */ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) @@ -103,7 +103,7 @@ static int dvb_usb_media_device_init(struct dvb_usb_adapter *adap) struct dvb_usb_device *d = adap->dev; struct usb_device *udev = d->udev; - mdev = v4l2_mc_usb_media_device_init(udev, d->desc->name); + mdev = media_device_usb_init(udev, d->desc->name); dvb_register_media_controller(&adap->dvb_adap, mdev); diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 389e95fb0211..0bae26325253 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3020,11 +3020,11 @@ static int em28xx_media_device_init(struct em28xx *dev, struct media_device *mdev; if (udev->product) { - mdev = v4l2_mc_usb_media_device_init(udev, udev->product); + mdev = media_device_usb_init(udev, udev->product); } else if (udev->manufacturer) { - mdev = v4l2_mc_usb_media_device_init(udev, udev->manufacturer); + mdev = media_device_usb_init(udev, udev->manufacturer); } else { - mdev = v4l2_mc_usb_media_device_init(udev, dev->name); + mdev = media_device_usb_init(udev, dev->name); } if (!mdev) diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index 4dac499ed28e..4a0def1e1528 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c @@ -27,7 +27,7 @@ along with this program. If not, see . #include #include #include -#include +#include #include "sms-cards.h" #include "smsendian.h" @@ -367,7 +367,7 @@ static void *siano_media_device_register(struct smsusb_device_t *dev, struct sms_board *board = sms_get_board(board_id); int ret; - mdev = v4l2_mc_usb_media_device_init(udev, board->name); + mdev = media_device_usb_init(udev, board->name); if (!mdev) return NULL; diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index 64eefb9ffb7e..4a1efa827fe2 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -1,7 +1,7 @@ /* * Media Controller ancillary functions * - * (c) 2016 Mauro Carvalho Chehab + * Copyright (c) 2016 Mauro Carvalho Chehab * * 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 @@ -15,83 +15,9 @@ */ #include -#include -#include #include #include - -struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, - const char *name) -{ -#ifdef CONFIG_PCI - struct media_device *mdev; - - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); - if (!mdev) - return NULL; - - mdev->dev = &pci_dev->dev; - - if (name) - strlcpy(mdev->model, name, sizeof(mdev->model)); - else - strlcpy(mdev->model, pci_name(pci_dev), sizeof(mdev->model)); - - sprintf(mdev->bus_info, "PCI:%s", pci_name(pci_dev)); - - mdev->hw_revision = (pci_dev->subsystem_vendor << 16) - | pci_dev->subsystem_device; - - mdev->driver_version = LINUX_VERSION_CODE; - - media_device_init(mdev); - - return mdev; -#else - return NULL; -#endif -} -EXPORT_SYMBOL_GPL(v4l2_mc_pci_media_device_init); - -struct media_device *__v4l2_mc_usb_media_device_init(struct usb_device *udev, - const char *board_name, - const char *driver_name) -{ -#ifdef CONFIG_USB - struct media_device *mdev; - - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); - if (!mdev) - return NULL; - - mdev->dev = &udev->dev; - - if (driver_name) - strlcpy(mdev->driver_name, driver_name, - sizeof(mdev->driver_name)); - - if (board_name) - strlcpy(mdev->model, board_name, sizeof(mdev->model)); - else if (udev->product) - strlcpy(mdev->model, udev->product, sizeof(mdev->model)); - else - strlcpy(mdev->model, "unknown model", sizeof(mdev->model)); - if (udev->serial) - strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); - usb_make_path(udev, mdev->bus_info, sizeof(mdev->bus_info)); - mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); - mdev->driver_version = LINUX_VERSION_CODE; - - media_device_init(mdev); - - return mdev; -#else - return NULL; -#endif -} -EXPORT_SYMBOL_GPL(__v4l2_mc_usb_media_device_init); - int v4l2_mc_create_media_graph(struct media_device *mdev) { diff --git a/include/media/media-device.h b/include/media/media-device.h index 165451bc3985..2d144fed936e 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -333,6 +333,10 @@ struct media_device { unsigned int notification); }; +/* We don't need to include pci.h or usb.h here */ +struct pci_dev; +struct usb_device; + #ifdef CONFIG_MEDIA_CONTROLLER /* Supported link_notify @notification values. */ @@ -541,6 +545,35 @@ struct media_device *media_device_find_devres(struct device *dev); /* Iterate over all links. */ #define media_device_for_each_link(link, mdev) \ list_for_each_entry(link, &(mdev)->links, graph_obj.list) + +/** + * media_device_pci_init() - create and initialize a + * struct &media_device from a PCI device. + * + * @pci_dev: pointer to struct pci_dev + * @name: media device name. If %NULL, the routine will use the default + * name for the pci device, given by pci_name() macro. + */ +struct media_device *media_device_pci_init(struct pci_dev *pci_dev, + const char *name); +/** + * __media_device_usb_init() - create and initialize a + * struct &media_device from a PCI device. + * + * @udev: pointer to struct usb_device + * @board_name: media device name. If %NULL, the routine will use the usb + * product name, if available. + * @driver_name: name of the driver. if %NULL, the routine will use the name + * given by udev->dev->driver->name, with is usually the wrong + * thing to do. + * + * NOTE: It is better to call media_device_usb_init() instead, as + * such macro fills driver_name with %KBUILD_MODNAME. + */ +struct media_device *__media_device_usb_init(struct usb_device *udev, + const char *board_name, + const char *driver_name); + #else static inline int media_device_register(struct media_device *mdev) { @@ -565,5 +598,25 @@ static inline struct media_device *media_device_find_devres(struct device *dev) { return NULL; } + +static inline +struct media_device *media_device_pci_init(struct pci_dev *pci_dev, + char *name) +{ + return NULL; +} + +static inline +struct media_device *__media_device_usb_init(struct usb_device *udev, + char *board_name, + char *driver_name) +{ + return NULL; +} + #endif /* CONFIG_MEDIA_CONTROLLER */ + +#define media_device_usb_init(udev, name) \ + __media_device_usb_init(udev, name, KBUILD_MODNAME) + #endif diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 79d84bb3573c..431380eb408b 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -116,57 +116,11 @@ struct usb_device; */ int v4l2_mc_create_media_graph(struct media_device *mdev); -/** - * v4l2_mc_pci_media_device_init() - create and initialize a - * struct &media_device from a PCI device. - * - * @pci_dev: pointer to struct pci_dev - * @name: media device name. If %NULL, the routine will use the default - * name for the pci device, given by pci_name() macro. - */ -struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, - const char *name); -/** - * __v4l2_mc_usb_media_device_init() - create and initialize a - * struct &media_device from a PCI device. - * - * @udev: pointer to struct usb_device - * @board_name: media device name. If %NULL, the routine will use the usb - * product name, if available. - * @driver_name: name of the driver. if %NULL, the routine will use the name - * given by udev->dev->driver->name, with is usually the wrong - * thing to do. - * - * NOTE: It is better to call v4l2_mc_usb_media_device_init() instead, as - * such macro fills driver_name with %KBUILD_MODNAME. - */ -struct media_device *__v4l2_mc_usb_media_device_init(struct usb_device *udev, - const char *board_name, - const char *driver_name); - #else static inline int v4l2_mc_create_media_graph(struct media_device *mdev) { return 0; } -static inline -struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, - char *name) -{ - return NULL; -} - -static inline -struct media_device *__v4l2_mc_usb_media_device_init(struct usb_device *udev, - char *board_name, - char *driver_name) -{ - return NULL; -} #endif - -#define v4l2_mc_usb_media_device_init(udev, name) \ - __v4l2_mc_usb_media_device_init(udev, name, KBUILD_MODNAME) - #endif -- cgit v1.2.3 From 6cf5dad17e913fce1ccb0c38e199eff15b0f03cc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Feb 2016 12:10:49 -0300 Subject: [media] media_device: move allocation out of media_device_*_init Right now, media_device_pci_init and media_device_usb_init does media_device allocation internaly. That preents its usage when the media_device struct is embedded on some other structure. Move memory allocation outside it, to make it more generic. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-device.c | 32 +++++++---------------------- drivers/media/pci/saa7134/saa7134-core.c | 3 ++- drivers/media/usb/au0828/au0828-core.c | 10 +++++---- drivers/media/usb/cx231xx/cx231xx-cards.c | 4 +++- drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 4 +++- drivers/media/usb/dvb-usb/dvb-usb-dvb.c | 6 +++++- drivers/media/usb/em28xx/em28xx-cards.c | 16 +++++++-------- drivers/media/usb/siano/smsusb.c | 4 +++- include/media/media-device.h | 32 ++++++++++++++++------------- 9 files changed, 55 insertions(+), 56 deletions(-) (limited to 'include') diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index fe376b6b5244..6613723f5eb8 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -755,16 +755,11 @@ struct media_device *media_device_find_devres(struct device *dev) } EXPORT_SYMBOL_GPL(media_device_find_devres); -struct media_device *media_device_pci_init(struct pci_dev *pci_dev, - const char *name) +void media_device_pci_init(struct media_device *mdev, + struct pci_dev *pci_dev, + const char *name) { #ifdef CONFIG_PCI - struct media_device *mdev; - - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); - if (!mdev) - return NULL; - mdev->dev = &pci_dev->dev; if (name) @@ -780,25 +775,16 @@ struct media_device *media_device_pci_init(struct pci_dev *pci_dev, mdev->driver_version = LINUX_VERSION_CODE; media_device_init(mdev); - - return mdev; -#else - return NULL; #endif } EXPORT_SYMBOL_GPL(media_device_pci_init); -struct media_device *__media_device_usb_init(struct usb_device *udev, - const char *board_name, - const char *driver_name) +void __media_device_usb_init(struct media_device *mdev, + struct usb_device *udev, + const char *board_name, + const char *driver_name) { #ifdef CONFIG_USB - struct media_device *mdev; - - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); - if (!mdev) - return NULL; - mdev->dev = &udev->dev; if (driver_name) @@ -818,10 +804,6 @@ struct media_device *__media_device_usb_init(struct usb_device *udev, mdev->driver_version = LINUX_VERSION_CODE; media_device_init(mdev); - - return mdev; -#else - return NULL; #endif } EXPORT_SYMBOL_GPL(__media_device_usb_init); diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c index 8ae65bb320a3..2e77a5a80119 100644 --- a/drivers/media/pci/saa7134/saa7134-core.c +++ b/drivers/media/pci/saa7134/saa7134-core.c @@ -1043,11 +1043,12 @@ static int saa7134_initdev(struct pci_dev *pci_dev, sprintf(dev->name, "saa%x[%d]", pci_dev->device, dev->nr); #ifdef CONFIG_MEDIA_CONTROLLER - dev->media_dev = media_device_pci_init(pci_dev, dev->name); + dev->media_dev = kzalloc(sizeof(*dev->media_dev), GFP_KERNEL); if (!dev->media_dev) { err = -ENOMEM; goto fail0; } + media_device_pci_init(dev->media_dev, pci_dev, dev->name); dev->v4l2_dev.mdev = dev->media_dev; #endif diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index cfcd08ec388f..5fea4adef90b 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -191,13 +191,15 @@ static int au0828_media_device_init(struct au0828_dev *dev, #ifdef CONFIG_MEDIA_CONTROLLER struct media_device *mdev; - if (!dev->board.name) - mdev = media_device_usb_init(udev, "unknown au0828"); - else - mdev = media_device_usb_init(udev, dev->board.name); + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); if (!mdev) return -ENOMEM; + if (!dev->board.name) + media_device_usb_init(mdev, udev, "unknown au0828"); + else + media_device_usb_init(mdev, udev, dev->board.name); + dev->media_dev = mdev; #endif return 0; diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 29bd7536feed..c63248a18823 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1212,10 +1212,12 @@ static int cx231xx_media_device_init(struct cx231xx *dev, #ifdef CONFIG_MEDIA_CONTROLLER struct media_device *mdev; - mdev = media_device_usb_init(udev, dev->board.name); + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); if (!mdev) return -ENOMEM; + media_device_usb_init(mdev, udev, dev->board.name); + dev->media_dev = mdev; #endif return 0; diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index 58250250a443..3fbb2cd19f5e 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -408,10 +408,12 @@ static int dvb_usbv2_media_device_init(struct dvb_usb_adapter *adap) struct dvb_usb_device *d = adap_to_d(adap); struct usb_device *udev = d->udev; - mdev = media_device_usb_init(udev, d->name); + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); if (!mdev) return -ENOMEM; + media_device_usb_init(mdev, udev, d->name); + dvb_register_media_controller(&adap->dvb_adap, mdev); dev_info(&d->udev->dev, "media controller created\n"); diff --git a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c index 7509408b0b8e..6477b04e95c7 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c @@ -103,7 +103,11 @@ static int dvb_usb_media_device_init(struct dvb_usb_adapter *adap) struct dvb_usb_device *d = adap->dev; struct usb_device *udev = d->udev; - mdev = media_device_usb_init(udev, d->desc->name); + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return -ENOMEM; + + media_device_usb_init(mdev, udev, d->desc->name); dvb_register_media_controller(&adap->dvb_adap, mdev); diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 0bae26325253..1f4047b3f3f7 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3019,17 +3019,17 @@ static int em28xx_media_device_init(struct em28xx *dev, #ifdef CONFIG_MEDIA_CONTROLLER struct media_device *mdev; - if (udev->product) { - mdev = media_device_usb_init(udev, udev->product); - } else if (udev->manufacturer) { - mdev = media_device_usb_init(udev, udev->manufacturer); - } else { - mdev = media_device_usb_init(udev, dev->name); - } - + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); if (!mdev) return -ENOMEM; + if (udev->product) + media_device_usb_init(mdev, udev, udev->product); + else if (udev->manufacturer) + media_device_usb_init(mdev, udev, udev->manufacturer); + else + media_device_usb_init(mdev, udev, dev->name); + dev->media_dev = mdev; #endif return 0; diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index 4a0def1e1528..c2e25876e93b 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c @@ -367,10 +367,12 @@ static void *siano_media_device_register(struct smsusb_device_t *dev, struct sms_board *board = sms_get_board(board_id); int ret; - mdev = media_device_usb_init(udev, board->name); + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); if (!mdev) return NULL; + media_device_usb_init(mdev, udev, board->name); + ret = media_device_register(mdev); if (ret) { media_device_cleanup(mdev); diff --git a/include/media/media-device.h b/include/media/media-device.h index 2d144fed936e..49dda6c7e664 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -550,16 +550,19 @@ struct media_device *media_device_find_devres(struct device *dev); * media_device_pci_init() - create and initialize a * struct &media_device from a PCI device. * + * @mdev: pointer to struct &media_device * @pci_dev: pointer to struct pci_dev * @name: media device name. If %NULL, the routine will use the default * name for the pci device, given by pci_name() macro. */ -struct media_device *media_device_pci_init(struct pci_dev *pci_dev, - const char *name); +void media_device_pci_init(struct media_device *mdev, + struct pci_dev *pci_dev, + const char *name); /** * __media_device_usb_init() - create and initialize a * struct &media_device from a PCI device. * + * @mdev: pointer to struct &media_device * @udev: pointer to struct usb_device * @board_name: media device name. If %NULL, the routine will use the usb * product name, if available. @@ -570,9 +573,10 @@ struct media_device *media_device_pci_init(struct pci_dev *pci_dev, * NOTE: It is better to call media_device_usb_init() instead, as * such macro fills driver_name with %KBUILD_MODNAME. */ -struct media_device *__media_device_usb_init(struct usb_device *udev, - const char *board_name, - const char *driver_name); +void __media_device_usb_init(struct media_device *mdev, + struct usb_device *udev, + const char *board_name, + const char *driver_name); #else static inline int media_device_register(struct media_device *mdev) @@ -599,24 +603,24 @@ static inline struct media_device *media_device_find_devres(struct device *dev) return NULL; } -static inline -struct media_device *media_device_pci_init(struct pci_dev *pci_dev, - char *name) +static inline void media_device_pci_init(struct media_device *mdev, + struct pci_dev *pci_dev, + char *name) { return NULL; } -static inline -struct media_device *__media_device_usb_init(struct usb_device *udev, - char *board_name, - char *driver_name) +static inline void __media_device_usb_init(struct media_device *mdev, + struct usb_device *udev, + char *board_name, + char *driver_name) { return NULL; } #endif /* CONFIG_MEDIA_CONTROLLER */ -#define media_device_usb_init(udev, name) \ - __media_device_usb_init(udev, name, KBUILD_MODNAME) +#define media_device_usb_init(mdev, udev, name) \ + __media_device_usb_init(mdev, udev, name, KBUILD_MODNAME) #endif -- cgit v1.2.3 From 5af557a6d2a077a8678879cf9498fbf8d5d81697 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 11 Feb 2016 21:41:18 -0200 Subject: [media] uapi/media.h: Declare interface types for ALSA Declare the interface types to be used on alsa for the new G_TOPOLOGY ioctl. Signed-off-by: Shuah Khan Acked-by: Takashi Iwai Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-entity.c | 16 ++++++++++++++++ include/uapi/linux/media.h | 10 ++++++++++ 2 files changed, 26 insertions(+) (limited to 'include') diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index 48d87c6f5e90..33628b8cba7e 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -65,6 +65,22 @@ static inline const char *intf_type(struct media_interface *intf) return "v4l2-subdev"; case MEDIA_INTF_T_V4L_SWRADIO: return "swradio"; + case MEDIA_INTF_T_ALSA_PCM_CAPTURE: + return "pcm-capture"; + case MEDIA_INTF_T_ALSA_PCM_PLAYBACK: + return "pcm-playback"; + case MEDIA_INTF_T_ALSA_CONTROL: + return "alsa-control"; + case MEDIA_INTF_T_ALSA_COMPRESS: + return "compress"; + case MEDIA_INTF_T_ALSA_RAWMIDI: + return "rawmidi"; + case MEDIA_INTF_T_ALSA_HWDEP: + return "hwdep"; + case MEDIA_INTF_T_ALSA_SEQUENCER: + return "sequencer"; + case MEDIA_INTF_T_ALSA_TIMER: + return "timer"; default: return "unknown-intf"; } diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 6aac2f035a5d..f53ede3efa2f 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -263,6 +263,7 @@ struct media_links_enum { #define MEDIA_INTF_T_DVB_BASE 0x00000100 #define MEDIA_INTF_T_V4L_BASE 0x00000200 +#define MEDIA_INTF_T_ALSA_BASE 0x00000300 /* Interface types */ @@ -278,6 +279,15 @@ struct media_links_enum { #define MEDIA_INTF_T_V4L_SUBDEV (MEDIA_INTF_T_V4L_BASE + 3) #define MEDIA_INTF_T_V4L_SWRADIO (MEDIA_INTF_T_V4L_BASE + 4) +#define MEDIA_INTF_T_ALSA_PCM_CAPTURE (MEDIA_INTF_T_ALSA_BASE) +#define MEDIA_INTF_T_ALSA_PCM_PLAYBACK (MEDIA_INTF_T_ALSA_BASE + 1) +#define MEDIA_INTF_T_ALSA_CONTROL (MEDIA_INTF_T_ALSA_BASE + 2) +#define MEDIA_INTF_T_ALSA_COMPRESS (MEDIA_INTF_T_ALSA_BASE + 3) +#define MEDIA_INTF_T_ALSA_RAWMIDI (MEDIA_INTF_T_ALSA_BASE + 4) +#define MEDIA_INTF_T_ALSA_HWDEP (MEDIA_INTF_T_ALSA_BASE + 5) +#define MEDIA_INTF_T_ALSA_SEQUENCER (MEDIA_INTF_T_ALSA_BASE + 6) +#define MEDIA_INTF_T_ALSA_TIMER (MEDIA_INTF_T_ALSA_BASE + 7) + /* * MC next gen API definitions * -- cgit v1.2.3 From 7a2eba12ff071dbc8e84ff4c2208d9f8bbb0046a Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 11 Feb 2016 21:41:20 -0200 Subject: [media] media: Add ALSA Media Controller function entities Add ALSA Media Controller capture, playback, and mixer function entity defines. [mchehab@osg.samsung.com: fix a trivial merge conflict and start MEDIA_ENT_AUDIO_F from 3000] Signed-off-by: Shuah Khan Acked-by: Takashi Iwai Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/media.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include') diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index f53ede3efa2f..95e126edb1c3 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -87,6 +87,13 @@ struct media_device_info { #define MEDIA_ENT_F_IF_VID_DECODER (MEDIA_ENT_F_BASE + 2001) #define MEDIA_ENT_F_IF_AUD_DECODER (MEDIA_ENT_F_BASE + 2002) +/* + * Audio Entity Functions + */ +#define MEDIA_ENT_F_AUDIO_CAPTURE (MEDIA_ENT_F_BASE + 3000) +#define MEDIA_ENT_F_AUDIO_PLAYBACK (MEDIA_ENT_F_BASE + 3001) +#define MEDIA_ENT_F_AUDIO_MIXER (MEDIA_ENT_F_BASE + 3002) + /* * Connectors */ -- cgit v1.2.3 From afcbdb55898b469606220fcb1868fc1bdd859675 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 11 Feb 2016 21:41:21 -0200 Subject: [media] media: Media Controller register/unregister entity_notify API Add new interfaces to register and unregister entity_notify hook to media device. These interfaces allow drivers to add hooks to take appropriate actions when new entities get added to a shared media device. For example, au0828 bridge driver registers an entity_notify hook to create links as needed between media graph nodes. [mchehab@osg.samsung.com: simple comments should be /* and not /**] Signed-off-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-device.c | 42 +++++++++++++++++++++++++++++++++ include/media/media-device.h | 56 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) (limited to 'include') diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 6613723f5eb8..17cd349e485f 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -542,6 +542,7 @@ static void media_device_release(struct media_devnode *mdev) int __must_check media_device_register_entity(struct media_device *mdev, struct media_entity *entity) { + struct media_entity_notify *notify, *next; unsigned int i; int ret; @@ -581,6 +582,11 @@ int __must_check media_device_register_entity(struct media_device *mdev, media_gobj_create(mdev, MEDIA_GRAPH_PAD, &entity->pads[i].graph_obj); + /* invoke entity_notify callbacks */ + list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) { + (notify)->notify(entity, notify->notify_data); + } + spin_unlock(&mdev->lock); return 0; @@ -614,6 +620,8 @@ static void __media_device_unregister_entity(struct media_entity *entity) /* Remove the entity */ media_gobj_destroy(&entity->graph_obj); + /* invoke entity_notify callbacks to handle entity removal?? */ + entity->graph_obj.mdev = NULL; } @@ -646,6 +654,7 @@ void media_device_init(struct media_device *mdev) INIT_LIST_HEAD(&mdev->interfaces); INIT_LIST_HEAD(&mdev->pads); INIT_LIST_HEAD(&mdev->links); + INIT_LIST_HEAD(&mdev->entity_notify); spin_lock_init(&mdev->lock); mutex_init(&mdev->graph_mutex); ida_init(&mdev->entity_internal_idx); @@ -691,11 +700,40 @@ int __must_check __media_device_register(struct media_device *mdev, } EXPORT_SYMBOL_GPL(__media_device_register); +int __must_check media_device_register_entity_notify(struct media_device *mdev, + struct media_entity_notify *nptr) +{ + spin_lock(&mdev->lock); + list_add_tail(&nptr->list, &mdev->entity_notify); + spin_unlock(&mdev->lock); + return 0; +} +EXPORT_SYMBOL_GPL(media_device_register_entity_notify); + +/* + * Note: Should be called with mdev->lock held. + */ +static void __media_device_unregister_entity_notify(struct media_device *mdev, + struct media_entity_notify *nptr) +{ + list_del(&nptr->list); +} + +void media_device_unregister_entity_notify(struct media_device *mdev, + struct media_entity_notify *nptr) +{ + spin_lock(&mdev->lock); + __media_device_unregister_entity_notify(mdev, nptr); + spin_unlock(&mdev->lock); +} +EXPORT_SYMBOL_GPL(media_device_unregister_entity_notify); + void media_device_unregister(struct media_device *mdev) { struct media_entity *entity; struct media_entity *next; struct media_interface *intf, *tmp_intf; + struct media_entity_notify *notify, *nextp; if (mdev == NULL) return; @@ -712,6 +750,10 @@ void media_device_unregister(struct media_device *mdev) list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list) __media_device_unregister_entity(entity); + /* Remove all entity_notify callbacks from the media device */ + list_for_each_entry_safe(notify, nextp, &mdev->entity_notify, list) + __media_device_unregister_entity_notify(mdev, notify); + /* Remove all interfaces from the media device */ list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces, graph_obj.list) { diff --git a/include/media/media-device.h b/include/media/media-device.h index 49dda6c7e664..5436c954281b 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -264,6 +264,22 @@ struct ida; struct device; +/** + * struct media_entity_notify - Media Entity Notify + * + * @list: List head + * @notify_data: Input data to invoke the callback + * @notify: Callback function pointer + * + * Drivers may register a callback to take action when + * new entities get registered with the media device. + */ +struct media_entity_notify { + struct list_head list; + void *notify_data; + void (*notify)(struct media_entity *entity, void *notify_data); +}; + /** * struct media_device - Media device * @dev: Parent device @@ -287,6 +303,7 @@ struct device; * @interfaces: List of registered interfaces * @pads: List of registered pads * @links: List of registered links + * @entity_notify: List of registered entity_notify callbacks * @lock: Entities list lock * @graph_mutex: Entities graph operation lock * @link_notify: Link state change notification callback @@ -324,6 +341,9 @@ struct media_device { struct list_head pads; struct list_head links; + /* notify callback list invoked when a new entity is registered */ + struct list_head entity_notify; + /* Protects the graph objects creation/removal */ spinlock_t lock; /* Serializes graph operations. */ @@ -506,6 +526,31 @@ int __must_check media_device_register_entity(struct media_device *mdev, */ void media_device_unregister_entity(struct media_entity *entity); +/** + * media_device_register_entity_notify() - Registers a media entity_notify + * callback + * + * @mdev: The media device + * @nptr: The media_entity_notify + * + * Note: When a new entity is registered, all the registered + * media_entity_notify callbacks are invoked. + */ + +int __must_check media_device_register_entity_notify(struct media_device *mdev, + struct media_entity_notify *nptr); + +/** + * media_device_unregister_entity_notify() - Unregister a media entity notify + * callback + * + * @mdev: The media device + * @nptr: The media_entity_notify + * + */ +void media_device_unregister_entity_notify(struct media_device *mdev, + struct media_entity_notify *nptr); + /** * media_device_get_devres() - get media device as device resource * creates if one doesn't exist @@ -594,6 +639,17 @@ static inline int media_device_register_entity(struct media_device *mdev, static inline void media_device_unregister_entity(struct media_entity *entity) { } +static inline int media_device_register_entity_notify( + struct media_device *mdev, + struct media_entity_notify *nptr) +{ + return 0; +} +static inline void media_device_unregister_entity_notify( + struct media_device *mdev, + struct media_entity_notify *nptr) +{ +} static inline struct media_device *media_device_get_devres(struct device *dev) { return NULL; -- cgit v1.2.3 From cd87ce873ffd7f9b593bcba40bc1a5b9e3053295 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 11 Feb 2016 21:41:22 -0200 Subject: [media] media: Media Controller enable/disable source handler API Add new fields to struct media_device to add enable_source, and disable_source handlers, and source_priv to stash driver private data that is used to run these handlers. The enable_source handler finds source entity for the passed in entity and checks if it is available. When link is found, it activates it. Disable source handler deactivates the link. Bridge driver is expected to implement and set these handlers. Signed-off-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- include/media/media-device.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'include') diff --git a/include/media/media-device.h b/include/media/media-device.h index 5436c954281b..0b946a895c3a 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -306,6 +306,11 @@ struct media_entity_notify { * @entity_notify: List of registered entity_notify callbacks * @lock: Entities list lock * @graph_mutex: Entities graph operation lock + * + * @source_priv: Driver Private data for enable/disable source handlers + * @enable_source: Enable Source Handler function pointer + * @disable_source: Disable Source Handler function pointer + * * @link_notify: Link state change notification callback * * This structure represents an abstract high-level media device. It allows easy @@ -317,6 +322,26 @@ struct media_entity_notify { * * @model is a descriptive model name exported through sysfs. It doesn't have to * be unique. + * + * @enable_source is a handler to find source entity for the + * sink entity and activate the link between them if source + * entity is free. Drivers should call this handler before + * accessing the source. + * + * @disable_source is a handler to find source entity for the + * sink entity and deactivate the link between them. Drivers + * should call this handler to release the source. + * + * Note: Bridge driver is expected to implement and set the + * handler when media_device is registered or when + * bridge driver finds the media_device during probe. + * Bridge driver sets source_priv with information + * necessary to run enable/disable source handlers. + * + * Use-case: find tuner entity connected to the decoder + * entity and check if it is available, and activate the + * the link between them from enable_source and deactivate + * from disable_source. */ struct media_device { /* dev->driver_data points to this struct. */ @@ -349,6 +374,11 @@ struct media_device { /* Serializes graph operations. */ struct mutex graph_mutex; + void *source_priv; + int (*enable_source)(struct media_entity *entity, + struct media_pipeline *pipe); + void (*disable_source)(struct media_entity *entity); + int (*link_notify)(struct media_link *link, u32 flags, unsigned int notification); }; -- cgit v1.2.3 From fb49f20438f361a60f9af555e5a69d91bb5e358f Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 11 Feb 2016 21:41:24 -0200 Subject: [media] media: Media Controller non-locking __media_entity_pipeline_start/stop() Add non-locking __media_entity_pipeline_start/stop() interfaces to be called from code paths that hold the graph_mutex. Signed-off-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-entity.c | 34 ++++++++++++++++++++++++---------- include/media/media-entity.h | 19 +++++++++++++++++++ 2 files changed, 43 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index bab592c6e785..bcd7464ab765 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -366,8 +366,8 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next); * Pipeline management */ -__must_check int media_entity_pipeline_start(struct media_entity *entity, - struct media_pipeline *pipe) +__must_check int __media_entity_pipeline_start(struct media_entity *entity, + struct media_pipeline *pipe) { struct media_device *mdev = entity->graph_obj.mdev; struct media_entity_graph *graph = &pipe->graph; @@ -375,8 +375,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity, struct media_link *link; int ret; - mutex_lock(&mdev->graph_mutex); - if (!pipe->streaming_count++) { ret = media_entity_graph_walk_init(&pipe->graph, mdev); if (ret) @@ -457,8 +455,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity, } } - mutex_unlock(&mdev->graph_mutex); - return 0; error: @@ -488,19 +484,28 @@ error_graph_walk_start: if (!--pipe->streaming_count) media_entity_graph_walk_cleanup(graph); - mutex_unlock(&mdev->graph_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(__media_entity_pipeline_start); +__must_check int media_entity_pipeline_start(struct media_entity *entity, + struct media_pipeline *pipe) +{ + struct media_device *mdev = entity->graph_obj.mdev; + int ret; + + mutex_lock(&mdev->graph_mutex); + ret = __media_entity_pipeline_start(entity, pipe); + mutex_unlock(&mdev->graph_mutex); return ret; } EXPORT_SYMBOL_GPL(media_entity_pipeline_start); -void media_entity_pipeline_stop(struct media_entity *entity) +void __media_entity_pipeline_stop(struct media_entity *entity) { - struct media_device *mdev = entity->graph_obj.mdev; struct media_entity_graph *graph = &entity->pipe->graph; struct media_pipeline *pipe = entity->pipe; - mutex_lock(&mdev->graph_mutex); WARN_ON(!pipe->streaming_count); media_entity_graph_walk_start(graph, entity); @@ -517,6 +522,15 @@ void media_entity_pipeline_stop(struct media_entity *entity) if (!--pipe->streaming_count) media_entity_graph_walk_cleanup(graph); +} +EXPORT_SYMBOL_GPL(__media_entity_pipeline_stop); + +void media_entity_pipeline_stop(struct media_entity *entity) +{ + struct media_device *mdev = entity->graph_obj.mdev; + + mutex_lock(&mdev->graph_mutex); + __media_entity_pipeline_stop(entity); mutex_unlock(&mdev->graph_mutex); } EXPORT_SYMBOL_GPL(media_entity_pipeline_stop); diff --git a/include/media/media-entity.h b/include/media/media-entity.h index fe485d367985..d58e29d3f239 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -832,6 +832,16 @@ media_entity_graph_walk_next(struct media_entity_graph *graph); */ __must_check int media_entity_pipeline_start(struct media_entity *entity, struct media_pipeline *pipe); +/** + * __media_entity_pipeline_start - Mark a pipeline as streaming + * + * @entity: Starting entity + * @pipe: Media pipeline to be assigned to all entities in the pipeline. + * + * Note: This is the non-locking version of media_entity_pipeline_start() + */ +__must_check int __media_entity_pipeline_start(struct media_entity *entity, + struct media_pipeline *pipe); /** * media_entity_pipeline_stop - Mark a pipeline as not streaming @@ -847,6 +857,15 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity, */ void media_entity_pipeline_stop(struct media_entity *entity); +/** + * __media_entity_pipeline_stop - Mark a pipeline as not streaming + * + * @entity: Starting entity + * + * Note: This is the non-locking version of media_entity_pipeline_stop() + */ +void __media_entity_pipeline_stop(struct media_entity *entity); + /** * media_devnode_create() - creates and initializes a device node interface * -- cgit v1.2.3 From d0a164f593ec770e5fc0dd9b003ac057559482c7 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 11 Feb 2016 21:41:25 -0200 Subject: [media] media: v4l-core add enable/disable source common interfaces Add a new interfaces to be used by v4l-core to invoke enable source and disable_source handlers in the media_device. The enable_source helper function invokes the enable_source handler to find media source entity connected to the entity and check is it is available or busy. If source is available, link is activated and pipeline is started. The disable_source helper function invokes the disable_source handler to deactivate and stop the pipeline. Signed-off-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-mc.c | 35 +++++++++++++++++++++ include/media/v4l2-dev.h | 1 + include/media/v4l2-mc.h | 65 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 100 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index 4a1efa827fe2..643686d40551 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -2,6 +2,7 @@ * Media Controller ancillary functions * * Copyright (c) 2016 Mauro Carvalho Chehab + * Copyright (C) 2016 Shuah Khan * * 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 @@ -16,7 +17,10 @@ #include #include +#include +#include #include +#include int v4l2_mc_create_media_graph(struct media_device *mdev) @@ -182,3 +186,34 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) return 0; } EXPORT_SYMBOL_GPL(v4l2_mc_create_media_graph); + +int v4l_enable_media_source(struct video_device *vdev) +{ + struct media_device *mdev = vdev->entity.graph_obj.mdev; + int ret; + + if (!mdev || !mdev->enable_source) + return 0; + ret = mdev->enable_source(&vdev->entity, &vdev->pipe); + if (ret) + return -EBUSY; + return 0; +} +EXPORT_SYMBOL_GPL(v4l_enable_media_source); + +void v4l_disable_media_source(struct video_device *vdev) +{ + struct media_device *mdev = vdev->entity.graph_obj.mdev; + + if (mdev && mdev->disable_source) + mdev->disable_source(&vdev->entity); +} +EXPORT_SYMBOL_GPL(v4l_disable_media_source); + +int v4l_vb2q_enable_media_source(struct vb2_queue *q) +{ + struct v4l2_fh *fh = q->owner; + + return v4l_enable_media_source(fh->vdev); +} +EXPORT_SYMBOL_GPL(v4l_vb2q_enable_media_source); diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index eeabf20e87a6..76056ab5c5bd 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -87,6 +87,7 @@ struct video_device #if defined(CONFIG_MEDIA_CONTROLLER) struct media_entity entity; struct media_intf_devnode *intf_devnode; + struct media_pipeline pipe; #endif /* device ops */ const struct v4l2_file_operations *fops; diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 431380eb408b..5cbc20923faf 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -18,6 +18,7 @@ #define _V4L2_MC_H #include +#include /** * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER @@ -116,11 +117,73 @@ struct usb_device; */ int v4l2_mc_create_media_graph(struct media_device *mdev); +/** + * v4l_enable_media_source() - Hold media source for exclusive use + * if free + * + * @vdev - poniter to struct video_device + * + * This interface calls enable_source handler to determine if + * media source is free for use. The enable_source handler is + * responsible for checking is the media source is free and + * start a pipeline between the media source and the media + * entity associated with the video device. This interface + * should be called from v4l2-core and dvb-core interfaces + * that change the source configuration. + * + * Return: returns zero on success or a negative error code. + */ +int v4l_enable_media_source(struct video_device *vdev); + +/** + * v4l_disable_media_source() - Release media source + * + * @vdev - poniter to struct video_device + * + * This interface calls disable_source handler to release + * the media source. The disable_source handler stops the + * active media pipeline between the media source and the + * media entity associated with the video device. + * + * Return: returns zero on success or a negative error code. + */ +void v4l_disable_media_source(struct video_device *vdev); + +/* + * v4l_vb2q_enable_media_tuner - Hold media source for exclusive use + * if free. + * @q - pointer to struct vb2_queue + * + * Wrapper for v4l_enable_media_source(). This function should + * be called from v4l2-core to enable the media source with + * pointer to struct vb2_queue as the input argument. Some + * v4l2-core interfaces don't have access to video device and + * this interface finds the struct video_device for the q and + * calls v4l_enable_media_source(). + */ +int v4l_vb2q_enable_media_source(struct vb2_queue *q); + #else + static inline int v4l2_mc_create_media_graph(struct media_device *mdev) { return 0; } +static int v4l_enable_media_source(struct video_device *vdev) +{ + return 0; +} + +static void v4l_disable_media_source(struct video_device *vdev) +{ + return; +} + +static int v4l_vb2q_enable_media_source(struct vb2_queue *q) +{ + return 0; +} + #endif -#endif +#endif /* _V4L2_MC_H */ -- cgit v1.2.3 From 697fe725f37aaa5fb15f581bc6e5b588f5fc8f7b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 26 Feb 2016 04:44:35 -0300 Subject: [media] media-device.h: fix compiler warning Fix these compiler warnings: media-git/include/media/media-device.h: In function 'media_device_pci_init': media-git/include/media/media-device.h:610:9: warning: 'return' with a value, in function returning void return NULL; ^ media-git/include/media/media-device.h: In function '__media_device_usb_init': media-git/include/media/media-device.h:618:9: warning: 'return' with a value, in function returning void return NULL; ^ Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- include/media/media-device.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/media/media-device.h b/include/media/media-device.h index 0b946a895c3a..32bbba7d8115 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -693,7 +693,6 @@ static inline void media_device_pci_init(struct media_device *mdev, struct pci_dev *pci_dev, char *name) { - return NULL; } static inline void __media_device_usb_init(struct media_device *mdev, @@ -701,7 +700,6 @@ static inline void __media_device_usb_init(struct media_device *mdev, char *board_name, char *driver_name) { - return NULL; } #endif /* CONFIG_MEDIA_CONTROLLER */ -- cgit v1.2.3 From 87294e9db50f34ac002e32669b2ff74b72d63584 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 29 Feb 2016 05:02:47 -0300 Subject: [media] media.h: use hex values for IF and AUDIO entities too Make the base offset hexadecimal to simplify debugging since the base addresses are hex too. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/media.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 2e2ab13a90b0..79960aefd356 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -84,15 +84,15 @@ struct media_device_info { * It is a responsibility of the master/bridge drivers to create links * for MEDIA_ENT_F_IF_VID_DECODER and MEDIA_ENT_F_IF_AUD_DECODER. */ -#define MEDIA_ENT_F_IF_VID_DECODER (MEDIA_ENT_F_BASE + 2001) -#define MEDIA_ENT_F_IF_AUD_DECODER (MEDIA_ENT_F_BASE + 2002) +#define MEDIA_ENT_F_IF_VID_DECODER (MEDIA_ENT_F_BASE + 0x02001) +#define MEDIA_ENT_F_IF_AUD_DECODER (MEDIA_ENT_F_BASE + 0x02002) /* * Audio Entity Functions */ -#define MEDIA_ENT_F_AUDIO_CAPTURE (MEDIA_ENT_F_BASE + 3000) -#define MEDIA_ENT_F_AUDIO_PLAYBACK (MEDIA_ENT_F_BASE + 3001) -#define MEDIA_ENT_F_AUDIO_MIXER (MEDIA_ENT_F_BASE + 3002) +#define MEDIA_ENT_F_AUDIO_CAPTURE (MEDIA_ENT_F_BASE + 0x03000) +#define MEDIA_ENT_F_AUDIO_PLAYBACK (MEDIA_ENT_F_BASE + 0x03001) +#define MEDIA_ENT_F_AUDIO_MIXER (MEDIA_ENT_F_BASE + 0x03002) /* * Connectors -- cgit v1.2.3 From 078600f514a12fd763ac84c86af68ef5b5267563 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Mar 2016 08:00:15 -0300 Subject: [media] rc-core: allow calling rc_open with device not initialized The device initialization completes only after calling input_register_device(). However, rc_open() can be called while the device is being registered by the input/evdev core. So, we can't expect that rc_dev->initialized to be true. Change the logic to don't require initialized == true at rc_open and change the type of initialized to be atomic. this way, we can check for it earlier where it is really needed, without needing to lock the mutex just for testing it. Tested with nuvoton_cir driver on a NUC5i7RYB with CIR integrated on it. Reported-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-main.c | 47 +++++++++++++++++++++------------------------- include/media/rc-core.h | 4 ++-- 2 files changed, 23 insertions(+), 28 deletions(-) (limited to 'include') diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index dcf20d9cbe09..4e9bbe735ae9 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -723,10 +724,6 @@ int rc_open(struct rc_dev *rdev) return -EINVAL; mutex_lock(&rdev->lock); - if (!rdev->initialized) { - rval = -EINVAL; - goto unlock; - } if (!rdev->users++ && rdev->open != NULL) rval = rdev->open(rdev); @@ -734,7 +731,6 @@ int rc_open(struct rc_dev *rdev) if (rval) rdev->users--; -unlock: mutex_unlock(&rdev->lock); return rval; @@ -879,11 +875,10 @@ static ssize_t show_protocols(struct device *device, if (!dev) return -EINVAL; + if (!atomic_read(&dev->initialized)) + return -ERESTARTSYS; + mutex_lock(&dev->lock); - if (!dev->initialized) { - mutex_unlock(&dev->lock); - return -EINVAL; - } if (fattr->type == RC_FILTER_NORMAL) { enabled = dev->enabled_protocols; @@ -1064,6 +1059,9 @@ static ssize_t store_protocols(struct device *device, if (!dev) return -EINVAL; + if (!atomic_read(&dev->initialized)) + return -ERESTARTSYS; + if (fattr->type == RC_FILTER_NORMAL) { IR_dprintk(1, "Normal protocol change requested\n"); current_protocols = &dev->enabled_protocols; @@ -1084,10 +1082,6 @@ static ssize_t store_protocols(struct device *device, } mutex_lock(&dev->lock); - if (!dev->initialized) { - rc = -EINVAL; - goto out; - } old_protocols = *current_protocols; new_protocols = old_protocols; @@ -1168,11 +1162,10 @@ static ssize_t show_filter(struct device *device, if (!dev) return -EINVAL; + if (!atomic_read(&dev->initialized)) + return -ERESTARTSYS; + mutex_lock(&dev->lock); - if (!dev->initialized) { - mutex_unlock(&dev->lock); - return -EINVAL; - } if (fattr->type == RC_FILTER_NORMAL) filter = &dev->scancode_filter; @@ -1223,6 +1216,9 @@ static ssize_t store_filter(struct device *device, if (!dev) return -EINVAL; + if (!atomic_read(&dev->initialized)) + return -ERESTARTSYS; + ret = kstrtoul(buf, 0, &val); if (ret < 0) return ret; @@ -1241,10 +1237,6 @@ static ssize_t store_filter(struct device *device, return -EINVAL; mutex_lock(&dev->lock); - if (!dev->initialized) { - ret = -EINVAL; - goto unlock; - } new_filter = *filter; if (fattr->mask) @@ -1431,6 +1423,7 @@ int rc_register_device(struct rc_dev *dev) dev->minor = minor; dev_set_name(&dev->dev, "rc%u", dev->minor); dev_set_drvdata(&dev->dev, dev); + atomic_set(&dev->initialized, 0); dev->dev.groups = dev->sysfs_groups; dev->sysfs_groups[attr++] = &rc_dev_protocol_attr_grp; @@ -1455,10 +1448,6 @@ int rc_register_device(struct rc_dev *dev) dev->input_dev->phys = dev->input_phys; dev->input_dev->name = dev->input_name; - 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, @@ -1474,6 +1463,11 @@ int rc_register_device(struct rc_dev *dev) */ dev->input_dev->rep[REP_PERIOD] = 125; + /* rc_open will be called here */ + rc = input_register_device(dev->input_dev); + if (rc) + goto out_table; + path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); dev_info(&dev->dev, "%s as %s\n", dev->input_name ?: "Unspecified device", path ?: "N/A"); @@ -1497,8 +1491,9 @@ int rc_register_device(struct rc_dev *dev) dev->enabled_protocols = rc_type; } + /* Allow the RC sysfs nodes to be accessible */ mutex_lock(&dev->lock); - dev->initialized = true; + atomic_set(&dev->initialized, 1); mutex_unlock(&dev->lock); IR_dprintk(1, "Registered rc%u (driver: %s, remote: %s, mode %s)\n", diff --git a/include/media/rc-core.h b/include/media/rc-core.h index c41dd7018fa8..0f77b3dffb37 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -60,7 +60,7 @@ enum rc_filter_type { /** * struct rc_dev - represents a remote control device * @dev: driver model's view of this device - * @initialized: true if the device init has completed + * @initialized: 1 if the device init has completed, 0 otherwise * @sysfs_groups: sysfs attribute groups * @input_name: name of the input child device * @input_phys: physical path to the input child device @@ -122,7 +122,7 @@ enum rc_filter_type { */ struct rc_dev { struct device dev; - bool initialized; + atomic_t initialized; const struct attribute_group *sysfs_groups[5]; const char *input_name; const char *input_phys; -- cgit v1.2.3 From bddc418787cccb2ba92b5e601d1d9b04f4668946 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Mar 2016 09:48:36 -0300 Subject: [media] au0828: use standard demod pads struct As we want au0828 to use the core function to create the MC graphs, use enum demod_pad_index instead of enum au8522_media_pads. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/au8522.h | 9 --------- drivers/media/dvb-frontends/au8522_decoder.c | 8 ++++---- drivers/media/dvb-frontends/au8522_priv.h | 3 ++- drivers/media/usb/au0828/au0828-core.c | 2 +- drivers/media/usb/au0828/au0828-video.c | 8 ++++---- include/media/v4l2-mc.h | 2 ++ 6 files changed, 13 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/drivers/media/dvb-frontends/au8522.h b/drivers/media/dvb-frontends/au8522.h index d7a997fada7f..78bf3f73e58d 100644 --- a/drivers/media/dvb-frontends/au8522.h +++ b/drivers/media/dvb-frontends/au8522.h @@ -89,13 +89,4 @@ enum au8522_audio_input { AU8522_AUDIO_NONE, AU8522_AUDIO_SIF, }; - -enum au8522_media_pads { - AU8522_PAD_INPUT, - AU8522_PAD_VID_OUT, - AU8522_PAD_VBI_OUT, - AU8522_PAD_AUDIO_OUT, - - AU8522_NUM_PADS -}; #endif /* __AU8522_H__ */ diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c index 0ab9f1eb8a29..add246382806 100644 --- a/drivers/media/dvb-frontends/au8522_decoder.c +++ b/drivers/media/dvb-frontends/au8522_decoder.c @@ -763,10 +763,10 @@ static int au8522_probe(struct i2c_client *client, v4l2_i2c_subdev_init(sd, client, &au8522_ops); #if defined(CONFIG_MEDIA_CONTROLLER) - state->pads[AU8522_PAD_INPUT].flags = MEDIA_PAD_FL_SINK; - state->pads[AU8522_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; - state->pads[AU8522_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; - state->pads[AU8522_PAD_AUDIO_OUT].flags = MEDIA_PAD_FL_SOURCE; + state->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + state->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; + state->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + state->pads[DEMOD_PAD_AUDIO_OUT].flags = MEDIA_PAD_FL_SOURCE; sd->entity.function = MEDIA_ENT_F_ATV_DECODER; ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(state->pads), diff --git a/drivers/media/dvb-frontends/au8522_priv.h b/drivers/media/dvb-frontends/au8522_priv.h index 505215a21ddd..f5a9438f6ce5 100644 --- a/drivers/media/dvb-frontends/au8522_priv.h +++ b/drivers/media/dvb-frontends/au8522_priv.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "dvb_frontend.h" #include "au8522.h" @@ -70,7 +71,7 @@ struct au8522_state { struct v4l2_ctrl_handler hdl; #ifdef CONFIG_MEDIA_CONTROLLER - struct media_pad pads[AU8522_NUM_PADS]; + struct media_pad pads[DEMOD_NUM_PADS]; #endif }; diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index ca1e5ebf3b6b..6da4e5749f3a 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -218,7 +218,7 @@ static void au0828_media_graph_notify(struct media_entity *new, switch (new->function) { case MEDIA_ENT_F_AUDIO_MIXER: ret = media_create_pad_link(dev->decoder, - AU8522_PAD_AUDIO_OUT, + DEMOD_PAD_AUDIO_OUT, new, 0, MEDIA_LNK_FL_ENABLED); if (ret) diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 1958de192608..b82deda02643 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -686,16 +686,16 @@ static int au0828_create_media_graph(struct au0828_dev *dev) if (tuner) { dev->tuner = tuner; ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, - decoder, AU8522_PAD_INPUT, 0); + decoder, DEMOD_PAD_IF_INPUT, 0); if (ret) return ret; } - ret = media_create_pad_link(decoder, AU8522_PAD_VID_OUT, + ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT, &dev->vdev.entity, 0, MEDIA_LNK_FL_ENABLED); if (ret) return ret; - ret = media_create_pad_link(decoder, AU8522_PAD_VBI_OUT, + ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT, &dev->vbi_dev.entity, 0, MEDIA_LNK_FL_ENABLED); if (ret) @@ -723,7 +723,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev) case AU0828_VMUX_SVIDEO: /* FIXME: fix the decoder PAD */ ret = media_create_pad_link(ent, 0, decoder, - AU8522_PAD_INPUT, 0); + DEMOD_PAD_IF_INPUT, 0); if (ret) return ret; break; diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 5cbc20923faf..9dff7adff64c 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -87,12 +87,14 @@ enum if_aud_dec_pad_index { * @DEMOD_PAD_IF_INPUT: IF input sink pad. * @DEMOD_PAD_VID_OUT: Video output source pad. * @DEMOD_PAD_VBI_OUT: Vertical Blank Interface (VBI) output source pad. + * @DEMOD_PAD_AUDIO_OUT: Audio output source pad. * @DEMOD_NUM_PADS: Maximum number of output pads. */ enum demod_pad_index { DEMOD_PAD_IF_INPUT, DEMOD_PAD_VID_OUT, DEMOD_PAD_VBI_OUT, + DEMOD_PAD_AUDIO_OUT, DEMOD_NUM_PADS }; -- cgit v1.2.3 From 5d8d8db851ef81337e7026b32a9d5a9cfb2271d5 Mon Sep 17 00:00:00 2001 From: Aviv Greenberg Date: Wed, 3 Feb 2016 15:08:52 -0200 Subject: [media] UVC: Add support for R200 depth camera Add support for Intel R200 depth camera in uvc driver. This includes adding new uvc GUIDs for the new pixel formats, adding new V4L pixel format definition to user api headers, and updating the uvc driver GUID-to-4cc tables with the new formats. Tested-by: Greenberg, Aviv D Signed-off-by: Aviv Greenberg Signed-off-by: Sakari Ailus Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 20 ++++++++++++++++++++ drivers/media/usb/uvc/uvcvideo.h | 12 ++++++++++++ include/uapi/linux/videodev2.h | 3 +++ 3 files changed, 35 insertions(+) (limited to 'include') diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 4e7148815a78..451e84e962e2 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -148,6 +148,26 @@ static struct uvc_format_desc uvc_fmts[] = { .guid = UVC_GUID_FORMAT_H264, .fcc = V4L2_PIX_FMT_H264, }, + { + .name = "Greyscale 8 L/R (Y8I)", + .guid = UVC_GUID_FORMAT_Y8I, + .fcc = V4L2_PIX_FMT_Y8I, + }, + { + .name = "Greyscale 12 L/R (Y12I)", + .guid = UVC_GUID_FORMAT_Y12I, + .fcc = V4L2_PIX_FMT_Y12I, + }, + { + .name = "Depth data 16-bit (Z16)", + .guid = UVC_GUID_FORMAT_Z16, + .fcc = V4L2_PIX_FMT_Z16, + }, + { + .name = "Bayer 10-bit (SRGGB10P)", + .guid = UVC_GUID_FORMAT_RW10, + .fcc = V4L2_PIX_FMT_SRGGB10P, + }, }; /* ------------------------------------------------------------------------ diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index f0f2391e1b43..7e4d3eea371b 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -119,6 +119,18 @@ #define UVC_GUID_FORMAT_H264 \ { 'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00, \ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_Y8I \ + { 'Y', '8', 'I', ' ', 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_Y12I \ + { 'Y', '1', '2', 'I', 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_Z16 \ + { 'Z', '1', '6', ' ', 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_RW10 \ + { 'R', 'W', '1', '0', 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} /* ------------------------------------------------------------------------ * Driver specific constants. diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 466458422385..e895975c5b0e 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -625,6 +625,9 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_JPGL v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */ #define V4L2_PIX_FMT_SE401 v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */ #define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */ +#define V4L2_PIX_FMT_Y8I v4l2_fourcc('Y', '8', 'I', ' ') /* Greyscale 8-bit L/R interleaved */ +#define V4L2_PIX_FMT_Y12I v4l2_fourcc('Y', '1', '2', 'I') /* Greyscale 12-bit L/R interleaved */ +#define V4L2_PIX_FMT_Z16 v4l2_fourcc('Z', '1', '6', ' ') /* Depth data 16-bit */ /* SDR formats - used only for Software Defined Radio devices */ #define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */ -- cgit v1.2.3 From 2899d35dc940613bed5912b26728f7947f48979e Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 15 Feb 2016 09:08:06 -0200 Subject: [media] media-entity: include linux/bug.h for WARN_ON WARN_ON is used by this header file, but none of its direct includes include asm/bug.h by way of linux/bug.h yet. Signed-off-by: Philipp Zabel Signed-off-by: Mauro Carvalho Chehab --- include/media/media-entity.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/media/media-entity.h b/include/media/media-entity.h index d58e29d3f239..6dc9e4e8cbd4 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -24,6 +24,7 @@ #define _MEDIA_ENTITY_H #include +#include #include #include #include -- cgit v1.2.3 From 4f27dba6d9ff2ab3c5aa371816b3a3c6a18d8d5d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 3 Mar 2016 12:14:33 -0300 Subject: [media] v4l2-mc: Fix parameter description .//include/media/v4l2-mc.h:138: warning: No description found for parameter 'vdev' .//include/media/v4l2-mc.h:152: warning: No description found for parameter 'vdev' Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-mc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 9dff7adff64c..f9477b88014d 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -123,7 +123,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev); * v4l_enable_media_source() - Hold media source for exclusive use * if free * - * @vdev - poniter to struct video_device + * @vdev: pointer to struct video_device * * This interface calls enable_source handler to determine if * media source is free for use. The enable_source handler is @@ -140,7 +140,7 @@ int v4l_enable_media_source(struct video_device *vdev); /** * v4l_disable_media_source() - Release media source * - * @vdev - poniter to struct video_device + * @vdev: pointer to struct video_device * * This interface calls disable_source handler to release * the media source. The disable_source handler stops the -- cgit v1.2.3 From 0c426c472b5585ed6e59160359c979506d45ae49 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sun, 21 Feb 2016 13:25:08 -0300 Subject: [media] media: Always keep a graph walk large enough around Re-create the graph walk object as needed in order to have one large enough available for all entities in the graph. This enumeration is used for pipeline power management in the future. [mchehab@osg.samsung.com: fix documentation bug: " warning: bad line: graph_mutex"] Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-device.c | 21 +++++++++++++++++++++ include/media/media-device.h | 3 +++ 2 files changed, 24 insertions(+) (limited to 'include') diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 17cd349e485f..a2353ecab687 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -589,6 +589,26 @@ int __must_check media_device_register_entity(struct media_device *mdev, spin_unlock(&mdev->lock); + mutex_lock(&mdev->graph_mutex); + if (mdev->entity_internal_idx_max + >= mdev->pm_count_walk.ent_enum.idx_max) { + struct media_entity_graph new = { .top = 0 }; + + /* + * Initialise the new graph walk before cleaning up + * the old one in order not to spoil the graph walk + * object of the media device if graph walk init fails. + */ + ret = media_entity_graph_walk_init(&new, mdev); + if (ret) { + mutex_unlock(&mdev->graph_mutex); + return ret; + } + media_entity_graph_walk_cleanup(&mdev->pm_count_walk); + mdev->pm_count_walk = new; + } + mutex_unlock(&mdev->graph_mutex); + return 0; } EXPORT_SYMBOL_GPL(media_device_register_entity); @@ -667,6 +687,7 @@ void media_device_cleanup(struct media_device *mdev) { ida_destroy(&mdev->entity_internal_idx); mdev->entity_internal_idx_max = 0; + media_entity_graph_walk_cleanup(&mdev->pm_count_walk); mutex_destroy(&mdev->graph_mutex); } EXPORT_SYMBOL_GPL(media_device_cleanup); diff --git a/include/media/media-device.h b/include/media/media-device.h index 32bbba7d8115..df74cfa7da4a 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -306,6 +306,8 @@ struct media_entity_notify { * @entity_notify: List of registered entity_notify callbacks * @lock: Entities list lock * @graph_mutex: Entities graph operation lock + * @pm_count_walk: Graph walk for power state walk. Access serialised using + * graph_mutex. * * @source_priv: Driver Private data for enable/disable source handlers * @enable_source: Enable Source Handler function pointer @@ -373,6 +375,7 @@ struct media_device { spinlock_t lock; /* Serializes graph operations. */ struct mutex graph_mutex; + struct media_entity_graph pm_count_walk; void *source_priv; int (*enable_source)(struct media_entity *entity, -- cgit v1.2.3 From 76413791a03f8fd8a3d793db135e19b6c2239664 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sun, 21 Feb 2016 13:25:09 -0300 Subject: [media] v4l: Add generic pipeline power management code When the Media controller framework was merged, it was decided not to add pipeline power management code for it was not seen generic. As a result, a number of drivers have copied the same piece of code, with same bugfixes done to them at different points of time (or not at all). Add these functions to V4L2. Their use is optional for drivers. [mchehab@osg.samsung.com: Fix merge conflicts] Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-mc.c | 183 +++++++++++++++++++++++++++++++++++++- include/media/v4l2-mc.h | 43 ++++++++- 2 files changed, 224 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index 621d2367363c..7291018cf1bf 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -3,6 +3,8 @@ * * Copyright (c) 2016 Mauro Carvalho Chehab * Copyright (C) 2016 Shuah Khan + * Copyright (C) 2006-2010 Nokia Corporation + * Copyright (c) 2016 Intel Corporation. * * 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 @@ -16,10 +18,15 @@ */ #include -#include +#include +#include #include +#include #include #include +#include +#include +#include #include int v4l2_mc_create_media_graph(struct media_device *mdev) @@ -236,3 +243,177 @@ int v4l_vb2q_enable_media_source(struct vb2_queue *q) return v4l_enable_media_source(fh->vdev); } EXPORT_SYMBOL_GPL(v4l_vb2q_enable_media_source); + +/* ----------------------------------------------------------------------------- + * Pipeline power management + * + * Entities must be powered up when part of a pipeline that contains at least + * one open video device node. + * + * To achieve this use the entity use_count field to track the number of users. + * For entities corresponding to video device nodes the use_count field stores + * the users count of the node. For entities corresponding to subdevs the + * use_count field stores the total number of users of all video device nodes + * in the pipeline. + * + * The v4l2_pipeline_pm_use() function must be called in the open() and + * close() handlers of video device nodes. It increments or decrements the use + * count of all subdev entities in the pipeline. + * + * To react to link management on powered pipelines, the link setup notification + * callback updates the use count of all entities in the source and sink sides + * of the link. + */ + +/* + * pipeline_pm_use_count - Count the number of users of a pipeline + * @entity: The entity + * + * Return the total number of users of all video device nodes in the pipeline. + */ +static int pipeline_pm_use_count(struct media_entity *entity, + struct media_entity_graph *graph) +{ + int use = 0; + + media_entity_graph_walk_start(graph, entity); + + while ((entity = media_entity_graph_walk_next(graph))) { + if (is_media_entity_v4l2_io(entity)) + use += entity->use_count; + } + + return use; +} + +/* + * pipeline_pm_power_one - Apply power change to an entity + * @entity: The entity + * @change: Use count change + * + * Change the entity use count by @change. If the entity is a subdev update its + * power state by calling the core::s_power operation when the use count goes + * from 0 to != 0 or from != 0 to 0. + * + * Return 0 on success or a negative error code on failure. + */ +static int pipeline_pm_power_one(struct media_entity *entity, int change) +{ + struct v4l2_subdev *subdev; + int ret; + + subdev = is_media_entity_v4l2_subdev(entity) + ? media_entity_to_v4l2_subdev(entity) : NULL; + + if (entity->use_count == 0 && change > 0 && subdev != NULL) { + ret = v4l2_subdev_call(subdev, core, s_power, 1); + if (ret < 0 && ret != -ENOIOCTLCMD) + return ret; + } + + entity->use_count += change; + WARN_ON(entity->use_count < 0); + + if (entity->use_count == 0 && change < 0 && subdev != NULL) + v4l2_subdev_call(subdev, core, s_power, 0); + + return 0; +} + +/* + * pipeline_pm_power - Apply power change to all entities in a pipeline + * @entity: The entity + * @change: Use count change + * + * Walk the pipeline to update the use count and the power state of all non-node + * entities. + * + * Return 0 on success or a negative error code on failure. + */ +static int pipeline_pm_power(struct media_entity *entity, int change, + struct media_entity_graph *graph) +{ + struct media_entity *first = entity; + int ret = 0; + + if (!change) + return 0; + + media_entity_graph_walk_start(graph, entity); + + while (!ret && (entity = media_entity_graph_walk_next(graph))) + if (is_media_entity_v4l2_subdev(entity)) + ret = pipeline_pm_power_one(entity, change); + + if (!ret) + return ret; + + media_entity_graph_walk_start(graph, first); + + while ((first = media_entity_graph_walk_next(graph)) + && first != entity) + if (is_media_entity_v4l2_subdev(first)) + pipeline_pm_power_one(first, -change); + + return ret; +} + +int v4l2_pipeline_pm_use(struct media_entity *entity, int use) +{ + struct media_device *mdev = entity->graph_obj.mdev; + int change = use ? 1 : -1; + int ret; + + mutex_lock(&mdev->graph_mutex); + + /* Apply use count to node. */ + entity->use_count += change; + WARN_ON(entity->use_count < 0); + + /* Apply power change to connected non-nodes. */ + ret = pipeline_pm_power(entity, change, &mdev->pm_count_walk); + if (ret < 0) + entity->use_count -= change; + + mutex_unlock(&mdev->graph_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(v4l2_pipeline_pm_use); + +int v4l2_pipeline_link_notify(struct media_link *link, u32 flags, + unsigned int notification) +{ + struct media_entity_graph *graph = &link->graph_obj.mdev->pm_count_walk; + struct media_entity *source = link->source->entity; + struct media_entity *sink = link->sink->entity; + int source_use; + int sink_use; + int ret = 0; + + source_use = pipeline_pm_use_count(source, graph); + sink_use = pipeline_pm_use_count(sink, graph); + + if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && + !(flags & MEDIA_LNK_FL_ENABLED)) { + /* Powering off entities is assumed to never fail. */ + pipeline_pm_power(source, -sink_use, graph); + pipeline_pm_power(sink, -source_use, graph); + return 0; + } + + if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH && + (flags & MEDIA_LNK_FL_ENABLED)) { + + ret = pipeline_pm_power(source, sink_use, graph); + if (ret < 0) + return ret; + + ret = pipeline_pm_power(sink, source_use, graph); + if (ret < 0) + pipeline_pm_power(source, -sink_use, graph); + } + + return ret; +} +EXPORT_SYMBOL_GPL(v4l2_pipeline_link_notify); diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index f9477b88014d..406f845034b9 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -2,6 +2,8 @@ * v4l2-mc.h - Media Controller V4L2 types and prototypes * * Copyright (C) 2016 Mauro Carvalho Chehab + * Copyright (C) 2006-2010 Nokia Corporation + * Copyright (c) 2016 Intel Corporation. * * 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 @@ -19,6 +21,7 @@ #include #include +#include /** * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER @@ -165,6 +168,45 @@ void v4l_disable_media_source(struct video_device *vdev); */ int v4l_vb2q_enable_media_source(struct vb2_queue *q); + +/** + * v4l2_pipeline_pm_use - Update the use count of an entity + * @entity: The entity + * @use: Use (1) or stop using (0) the entity + * + * Update the use count of all entities in the pipeline and power entities on or + * off accordingly. + * + * This function is intended to be called in video node open (use == + * 1) and release (use == 0). It uses struct media_entity.use_count to + * track the power status. The use of this function should be paired + * with v4l2_pipeline_link_notify(). + * + * Return 0 on success or a negative error code on failure. Powering entities + * off is assumed to never fail. No failure can occur when the use parameter is + * set to 0. + */ +int v4l2_pipeline_pm_use(struct media_entity *entity, int use); + + +/** + * v4l2_pipeline_link_notify - Link management notification callback + * @link: The link + * @flags: New link flags that will be applied + * @notification: The link's state change notification type (MEDIA_DEV_NOTIFY_*) + * + * React to link management on powered pipelines by updating the use count of + * all entities in the source and sink sides of the link. Entities are powered + * on or off accordingly. The use of this function should be paired + * with v4l2_pipeline_pm_use(). + * + * Return 0 on success or a negative error code on failure. Powering entities + * off is assumed to never fail. This function will not fail for disconnection + * events. + */ +int v4l2_pipeline_link_notify(struct media_link *link, u32 flags, + unsigned int notification); + #else static inline int v4l2_mc_create_media_graph(struct media_device *mdev) @@ -186,6 +228,5 @@ static int v4l_vb2q_enable_media_source(struct vb2_queue *q) { return 0; } - #endif #endif /* _V4L2_MC_H */ -- cgit v1.2.3 From a77bf7048addfbd59ec2208f3172207d90d42c9a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 3 Mar 2016 12:30:51 -0300 Subject: v4l2-mc.h: Add stubs for the V4L2 PM/pipeline routines Let's add stubs for the case where the Kernel gets compiled without MEDIA_CONTROLLER. Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-mc.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 406f845034b9..144b152e0362 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -207,7 +207,7 @@ int v4l2_pipeline_pm_use(struct media_entity *entity, int use); int v4l2_pipeline_link_notify(struct media_link *link, u32 flags, unsigned int notification); -#else +#else /* CONFIG_MEDIA_CONTROLLER */ static inline int v4l2_mc_create_media_graph(struct media_device *mdev) { @@ -228,5 +228,17 @@ static int v4l_vb2q_enable_media_source(struct vb2_queue *q) { return 0; } -#endif + +int v4l2_pipeline_pm_use(struct media_entity *entity, int use); +{ + return 0; +} + +int v4l2_pipeline_link_notify(struct media_link *link, u32 flags, + unsigned int notification); +{ + return 0; +} + +#endif /* CONFIG_MEDIA_CONTROLLER */ #endif /* _V4L2_MC_H */ -- cgit v1.2.3 From 0629e991a25a9b56a70f9f0c327aad8ae1471dbf Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 22 Feb 2016 17:47:04 -0300 Subject: [media] media: Move media_get_uptr() macro out of the media.h user space header The media_get_uptr() macro is mostly useful only for the IOCTL handling code in media-device.c so move it there. Signed-off-by: Sakari Ailus Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-device.c | 5 +++++ include/uapi/linux/media.h | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index a2353ecab687..c89dfef0c4c5 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -40,6 +40,11 @@ * Userspace API */ +static inline void __user *media_get_uptr(__u64 arg) +{ + return (void __user *)(uintptr_t)arg; +} + static int media_device_open(struct file *filp) { return 0; diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 79960aefd356..71fb8e3dce06 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -375,11 +375,6 @@ struct media_v2_topology { __u64 ptr_links; }; -static inline void __user *media_get_uptr(__u64 arg) -{ - return (void __user *)(uintptr_t)arg; -} - /* ioctls */ #define MEDIA_IOC_DEVICE_INFO _IOWR('|', 0x00, struct media_device_info) -- cgit v1.2.3 From 9532e6bbef87149f35de7f980f8bd61195936a78 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 3 Mar 2016 04:37:14 -0300 Subject: [media] v4l2-mc.h: fix compiler warnings Fix these warnings when CONFIG_MEDIA_CONTROLLER is not defined: In file included from drivers/media/v4l2-core/v4l2-fh.c:32:0: include/media/v4l2-mc.h:173:12: warning: 'v4l_enable_media_source' defined but not used [-Wunused-function] static int v4l_enable_media_source(struct video_device *vdev) ^ include/media/v4l2-mc.h:183:12: warning: 'v4l_vb2q_enable_media_source' defined but not used [-Wunused-function] static int v4l_vb2q_enable_media_source(struct vb2_queue *q) ^ In file included from include/media/tuner.h:23:0, from drivers/media/tuners/tuner-types.c:9: include/media/v4l2-mc.h:173:12: warning: 'v4l_enable_media_source' defined but not used [-Wunused-function] static int v4l_enable_media_source(struct video_device *vdev) ^ include/media/v4l2-mc.h:178:13: warning: 'v4l_disable_media_source' defined but not used [-Wunused-function] static void v4l_disable_media_source(struct video_device *vdev) ^ Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-mc.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 144b152e0362..96cfca9cd338 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -214,17 +214,17 @@ static inline int v4l2_mc_create_media_graph(struct media_device *mdev) return 0; } -static int v4l_enable_media_source(struct video_device *vdev) +static inline int v4l_enable_media_source(struct video_device *vdev) { return 0; } -static void v4l_disable_media_source(struct video_device *vdev) +static inline void v4l_disable_media_source(struct video_device *vdev) { return; } -static int v4l_vb2q_enable_media_source(struct vb2_queue *q) +static inline int v4l_vb2q_enable_media_source(struct vb2_queue *q) { return 0; } -- cgit v1.2.3 From 64bd1971decc2c2f81ca16370f8ee09bdcb1b49d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 3 Mar 2016 10:47:33 -0300 Subject: [media] media.h: always start with 1 for the audio entities Start the audio defines with BASE + 0x03001 instead of 0x03000. This is consistent with the other defines, and I think it is good practice not to start with 0, just in case we want to do something like (id & 0xfff) in the future and treat the value 0 as a special case. Signed-off-by: Hans Verkuil Suggested-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/media.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 71fb8e3dce06..52f5834dcc41 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -90,9 +90,9 @@ struct media_device_info { /* * Audio Entity Functions */ -#define MEDIA_ENT_F_AUDIO_CAPTURE (MEDIA_ENT_F_BASE + 0x03000) -#define MEDIA_ENT_F_AUDIO_PLAYBACK (MEDIA_ENT_F_BASE + 0x03001) -#define MEDIA_ENT_F_AUDIO_MIXER (MEDIA_ENT_F_BASE + 0x03002) +#define MEDIA_ENT_F_AUDIO_CAPTURE (MEDIA_ENT_F_BASE + 0x03001) +#define MEDIA_ENT_F_AUDIO_PLAYBACK (MEDIA_ENT_F_BASE + 0x03002) +#define MEDIA_ENT_F_AUDIO_MIXER (MEDIA_ENT_F_BASE + 0x03003) /* * Connectors -- cgit v1.2.3 From 1e89f58499f3351a3b3c61dae8213fe3cd24a476 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 4 Mar 2016 05:46:58 -0300 Subject: [media] v4l2-mc.h: fix yet more compiler errors The newly added functions have an extra semicolon, which prevents compilation, and they need to be marked inline: In file included from ../include/media/tuner.h:23:0, from ../drivers/media/tuners/tuner-simple.c:10: ../include/media/v4l2-mc.h:233:1: error: expected identifier or '(' before '{' token Remove spurious return, remove copy-and-pasted semi-colons, add static inline. Fixes: a77bf7048add ("v4l2-mc.h: Add stubs for the V4L2 PM/pipeline routines") Signed-off-by: Arnd Bergmann Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-mc.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 96cfca9cd338..98a938aabdfb 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -221,7 +221,6 @@ static inline int v4l_enable_media_source(struct video_device *vdev) static inline void v4l_disable_media_source(struct video_device *vdev) { - return; } static inline int v4l_vb2q_enable_media_source(struct vb2_queue *q) @@ -229,13 +228,13 @@ static inline int v4l_vb2q_enable_media_source(struct vb2_queue *q) return 0; } -int v4l2_pipeline_pm_use(struct media_entity *entity, int use); +static inline int v4l2_pipeline_pm_use(struct media_entity *entity, int use) { return 0; } -int v4l2_pipeline_link_notify(struct media_link *link, u32 flags, - unsigned int notification); +static inline int v4l2_pipeline_link_notify(struct media_link *link, u32 flags, + unsigned int notification) { return 0; } -- cgit v1.2.3