This patch series updates ALSA driver, and au0828 core
driver to use Managed Media controller API and Media
Controller API to share tuner.
Media Controller Next Generation API has been enhanced
to add two new interfaces to register and unregister
entity_notify hooks to allow drivers to take appropriate
actions when as new entities get added to the shared media
device.
Mauro and Takashi: I am hoping you can both coordinate
and decide on ALSA patches once the reviews are done
and the patches look good.
Design Highlights:
1. ALSA to check for resources and hold in snd_usb_hw_params(),
and release from snd_usb_hw_free(). This change fixed the
lockdep warnings seen when resources were held in
TRIGGER_START and released from TRIGGER_STOP which could
run in IRQ context. I acknowledge Clemens Ladisch for
suggesting the correct places to hold/free resources to
avoid IRQ path complications.
2. The Bridge driver (au0828) owns and drives the graph creation
as well as enabling and disabling tuner. It also keeps state
information to avoid graph walks in enable_source and
disable_source handler. I acknowledge Hans Verkuil for his
suggestions and ideas for this change.
Tested exclusion between digital, analog, and audio to ensure
when tuner has an active link to DVB FE, analog, and audio will
detect and honor the tuner busy conditions and vice versa.
Please find the graphs generated using mc_nextgen_test tool at
various points during testing at:
https://drive.google.com/folderview?id=0B0NIL0BQg-AlRndaaXViSXdPeTA&usp=sharing
This patch series is a rebase and update to the latest Media
Controller Next Gen API of the Media Controller Next Generation
API port.
Rebase highlights:
1. Changes to videobuf2 framework required additional
v4l2 helper function to enable the tuner from
vb2_core_streamon(). Patch 9 has this work.
2. Media device initialization and registration steps
are now split in the latest Media Controller Next Gen
API. This required changes to au0828 and ALSA to coordinate
initialization and registration of the Managed Media Device
they share. Patch 19 shows au0828 changes. ALSA changes
for this are folded into the main ALSA patch 26.
3. Media device unregistration does more cleanup now. As a
result, au0828 and ALSA need to coordinate so media device
is done only once. These changes are in patches: 29, 30,
and 31.
4. In addition, media device resources cleanup gets done
before snd_card_disconnect(). This work is in patch 30.
Media Controller Next Generation API port from Media Controller API:
The patch series below was a port of the Patch v3 - Media Controller API
to Next Gen API and Mixer patch update to address comments and bug fixes:
https://www.mail-archive.com/linux-media@vger.kernel.org/msg93086.htmlhttps://www.mail-archive.com/linux-media@vger.kernel.org/msg93417.html
Patch v3 - Media Controller API:
https://www.mail-archive.com/linux-media@vger.kernel.org/msg92572.html
Mauro Carvalho Chehab (1):
uapi/media.h: Declare interface types for ALSA
Shuah Khan (30):
media: Add ALSA Media Controller function entities
media: Media Controller register/unregister entity_notify API
media: Media Controller enable/disable source handler API
media: Media Controller fix to not let stream_count go negative
media: Media Controller export non locking __media_entity_setup_link()
media: Media Controller non-locking
__media_entity_pipeline_start/stop()
media: v4l-core add v4l_enable/disable_media_tuner() helper functions
media: v4l2-core add v4l_vb2q_enable_media_tuner() helper
media: Move au8522_media_pads enum to au8522.h from au8522_priv.h
media: au8522 change to create MC pad for ALSA Audio Out
media: au0828 Use au8522_media_pads enum for pad defines
media: au0828 fix au0828_create_media_graph() entity checks
media: Change v4l-core to check for tuner availability
media: dvb-frontend invoke enable/disable_source handlers
media: au0828 video remove au0828_enable_analog_tuner()
media: au0828 video change to use v4l_enable_media_tuner()
media: au0828 change to use Managed Media Controller API
media: au0828 handle media_init and media_register window
media: au0828 change to register/unregister entity_notify hook
media: au0828 create tuner to decoder link in deactivated state
media: dvb-core create tuner to demod pad link in disabled state
media: au0828 implement enable_source and disable_source handlers
media: au0828 fix null pointer reference in
au0828_create_media_graph()
media: au0828 fix to not call media_device_unregister_entity_notify()
sound/usb: Update ALSA driver to use Managed Media Controller API
sound/usb: Create media mixer function and control interface entities
media: au0828 create link between ALSA Mixer and decoder
media: track media device unregister in progress
sound/usb: Check media device unregister progress state
media: au0828 change to check media device unregister progress state
drivers/media/dvb-core/dvb_frontend.c | 139 ++---------
drivers/media/dvb-core/dvb_frontend.h | 3 +
drivers/media/dvb-core/dvbdev.c | 3 +-
drivers/media/dvb-frontends/au8522.h | 8 +
drivers/media/dvb-frontends/au8522_decoder.c | 1 +
drivers/media/dvb-frontends/au8522_priv.h | 8 -
drivers/media/media-device.c | 66 ++++-
drivers/media/media-entity.c | 65 +++--
drivers/media/usb/au0828/au0828-core.c | 355 ++++++++++++++++++++++-----
drivers/media/usb/au0828/au0828-video.c | 75 +-----
drivers/media/usb/au0828/au0828.h | 9 +
drivers/media/v4l2-core/v4l2-dev.c | 48 ++++
drivers/media/v4l2-core/v4l2-fh.c | 1 +
drivers/media/v4l2-core/v4l2-ioctl.c | 29 +++
drivers/media/v4l2-core/videobuf2-core.c | 4 +
include/media/media-device.h | 61 +++++
include/media/media-entity.h | 12 +
include/media/v4l2-dev.h | 5 +
include/uapi/linux/media.h | 17 +-
sound/usb/Makefile | 15 +-
sound/usb/card.c | 16 ++
sound/usb/card.h | 1 +
sound/usb/media.c | 325 ++++++++++++++++++++++++
sound/usb/media.h | 75 ++++++
sound/usb/mixer.h | 1 +
sound/usb/pcm.c | 26 +-
sound/usb/quirks-table.h | 1 +
sound/usb/quirks.c | 9 +-
sound/usb/stream.c | 1 +
sound/usb/usbaudio.h | 2 +
30 files changed, 1111 insertions(+), 270 deletions(-)
create mode 100644 sound/usb/media.c
create mode 100644 sound/usb/media.h
--
2.5.0
Change s_input, s_fmt, s_tuner, s_frequency, querystd,
s_hw_freq_seek, and vb2_core_streamon interfaces that
alter the tuner configuration to check for tuner availability
by calling v4l_enable_media_tuner(). If tuner isn't free,
return -EBUSY. v4l_disable_media_tuner() is called from
v4l2_fh_exit() to release the tuner. vb2_core_streamon()
uses v4l_vb2q_enable_media_tuner().
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/v4l2-core/v4l2-fh.c | 1 +
drivers/media/v4l2-core/v4l2-ioctl.c | 29 +++++++++++++++++++++++++++++
drivers/media/v4l2-core/videobuf2-core.c | 4 ++++
3 files changed, 34 insertions(+)
@@ -1041,6 +1041,12 @@ static int v4l_querycap(const struct v4l2_ioctl_ops *ops,staticintv4l_s_input(conststructv4l2_ioctl_ops*ops,structfile*file,void*fh,void*arg){+structvideo_device*vfd=video_devdata(file);+intret;++ret=v4l_enable_media_tuner(vfd);+if(ret)+returnret;returnops->vidioc_s_input(file,fh,*(unsignedint*)arg);}
@@ -1448,6 +1454,9 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,boolis_tx=vfd->vfl_dir!=VFL_DIR_RX;intret;+ret=v4l_enable_media_tuner(vfd);+if(ret)+returnret;v4l_sanitize_format(p);switch(p->type){
@@ -1637,7 +1646,11 @@ static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops,{structvideo_device*vfd=video_devdata(file);structv4l2_tuner*p=arg;+intret;+ret=v4l_enable_media_tuner(vfd);+if(ret)+returnret;p->type=(vfd->vfl_type==VFL_TYPE_RADIO)?V4L2_TUNER_RADIO:V4L2_TUNER_ANALOG_TV;returnops->vidioc_s_tuner(file,fh,p);
@@ -1691,7 +1704,11 @@ static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops,structvideo_device*vfd=video_devdata(file);conststructv4l2_frequency*p=arg;enumv4l2_tuner_typetype;+intret;+ret=v4l_enable_media_tuner(vfd);+if(ret)+returnret;if(vfd->vfl_type==VFL_TYPE_SDR){if(p->type!=V4L2_TUNER_SDR&&p->type!=V4L2_TUNER_RF)return-EINVAL;
@@ -1746,7 +1763,11 @@ static int v4l_s_std(const struct v4l2_ioctl_ops *ops,{structvideo_device*vfd=video_devdata(file);v4l2_std_idid=*(v4l2_std_id*)arg,norm;+intret;+ret=v4l_enable_media_tuner(vfd);+if(ret)+returnret;norm=id&vfd->tvnorms;if(vfd->tvnorms&&!norm)/* Check if std is supported */return-EINVAL;
@@ -1760,7 +1781,11 @@ static int v4l_querystd(const struct v4l2_ioctl_ops *ops,{structvideo_device*vfd=video_devdata(file);v4l2_std_id*p=arg;+intret;+ret=v4l_enable_media_tuner(vfd);+if(ret)+returnret;/**Ifnosignalisdetected,thenthedrivershouldreturn*V4L2_STD_UNKNOWN.Otherwiseitshouldreturntvnormswith
@@ -1779,7 +1804,11 @@ static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops,structvideo_device*vfd=video_devdata(file);structv4l2_hw_freq_seek*p=arg;enumv4l2_tuner_typetype;+intret;+ret=v4l_enable_media_tuner(vfd);+if(ret)+returnret;/* s_hw_freq_seek is not supported for SDR for now */if(vfd->vfl_type==VFL_TYPE_SDR)return-EINVAL;
au0828_create_media_graph() doesn't do any checks to determine,
if vbi_dev, vdev, and input entities have been registered prior
to creating pad links. Checking graph_obj.mdev field works as
the graph_obj.mdev field gets initialized in the entity register
interface. Fix it to check graph_obj.mdev field before creating
pad links.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-core.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
au0828_enable_analog_tuner() is no longer needed with
v4l2-core and au0828-video invoking enable_source and
disable_source handlers. In addition, it is unnecessary
to check for tuner availability in queue_setup() as
v4l2-core handles the tuner availability checks.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-video.c | 61 ---------------------------------
1 file changed, 61 deletions(-)
Checking for tuner availability from frontend thread start
disrupts video stream. Change to check for tuner and start
pipeline from frontend open instead and stop pipeline from
frontend release. In addition, make a change to invoke
enable_source and disable_source handlers to check for
tuner availability. The enable_source handler finds tuner
entity connected to the decoder and check is it is available
or busy. If tuner is available, link is activated and pipeline
is started. The disable_source handler to deactivate and stop
the pipeline. dvb_enable_media_tuner() is removed as it is no
longer necessary with dvb invoking enable_source and
disable_source handlers. pipe_start_entity field is removed
and pipe field is moved to dvb_frontend from dvb_frontend_private.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/dvb-core/dvb_frontend.c | 139 +++++-----------------------------
drivers/media/dvb-core/dvb_frontend.h | 3 +
2 files changed, 24 insertions(+), 118 deletions(-)
@@ -596,104 +591,12 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe)wake_up_interruptible(&fepriv->wait_queue);}-/**-*dvb_enable_media_tuner()-triestoenabletheDVBtuner-*-*@fe:structdvb_frontendpointer-*-*Thisfunctionensuresthatjustonemediatunerisenabledforagiven-*frontend.Ithastwodifferentbehaviors:-*-Fortrivialdeviceswithjustonetuner:-*itjustenablestheexistingtuner->felink-*-Fordeviceswithmorethanonetuner:-*Itisuptothedrivertoimplementthelogicthatwillenableonetuner-*anddisabletheotherones.However,ifmorethanonetunerisenabledfor-*thesamefrontend,itwillprintanerrormessageandreturn-EINVAL.-*-*Atreturn,itwillreturntheerrorcodereturnedbymedia_entity_setup_link,-*or0ifeverythingisOK,ifnotunerislinkedtothefrontendorifthe-*mdevisNULL.-*/-#ifdef CONFIG_MEDIA_CONTROLLER_DVB-staticintdvb_enable_media_tuner(structdvb_frontend*fe)-{-structdvb_frontend_private*fepriv=fe->frontend_priv;-structdvb_adapter*adapter=fe->dvb;-structmedia_device*mdev=adapter->mdev;-structmedia_entity*entity,*source;-structmedia_link*link,*found_link=NULL;-intret,n_links=0,active_links=0;--fepriv->pipe_start_entity=NULL;--if(!mdev)-return0;--entity=fepriv->dvbdev->entity;-fepriv->pipe_start_entity=entity;--list_for_each_entry(link,&entity->links,list){-if(link->sink->entity==entity){-found_link=link;-n_links++;-if(link->flags&MEDIA_LNK_FL_ENABLED)-active_links++;-}-}--if(!n_links||active_links==1||!found_link)-return0;--/*-*Ifafrontendhasmorethanonetunerlinked,itisuptothedriver-*toselectwithonewillbetheactiveone,asthefrontendcorecan't-*guess.Ifthedriverdoesn'tdothat,itisabug.-*/-if(n_links>1&&active_links!=1){-dev_err(fe->dvb->device,-"WARNING: there are %d active links among %d tuners. This is a driver's bug!\n",-active_links,n_links);-return-EINVAL;-}--source=found_link->source->entity;-fepriv->pipe_start_entity=source;-list_for_each_entry(link,&source->links,list){-structmedia_entity*sink;-intflags=0;--sink=link->sink->entity;-if(sink==entity)-flags=MEDIA_LNK_FL_ENABLED;--ret=media_entity_setup_link(link,flags);-if(ret){-dev_err(fe->dvb->device,-"Couldn't change link %s->%s to %s. Error %d\n",-source->name,sink->name,-flags?"enabled":"disabled",-ret);-returnret;-}else-dev_dbg(fe->dvb->device,-"link %s->%s was %s\n",-source->name,sink->name,-flags?"ENABLED":"disabled");-}-return0;-}-#endif-staticintdvb_frontend_thread(void*data){structdvb_frontend*fe=data;structdvb_frontend_private*fepriv=fe->frontend_priv;enumfe_statuss;enumdvbfe_algoalgo;-#ifdef CONFIG_MEDIA_CONTROLLER_DVB-intret;-#endif-boolre_tune=false;boolsemheld=false;
@@ -706,20 +609,6 @@ static int dvb_frontend_thread(void *data)fepriv->wakeup=0;fepriv->reinitialise=0;-#ifdef CONFIG_MEDIA_CONTROLLER_DVB-ret=dvb_enable_media_tuner(fe);-if(ret){-/* FIXME: return an error if it fails */-dev_info(fe->dvb->device,-"proceeding with FE task\n");-}elseif(fepriv->pipe_start_entity){-ret=media_entity_pipeline_start(fepriv->pipe_start_entity,-&fepriv->pipe);-if(ret)-returnret;-}-#endif-dvb_frontend_init(fe);set_freezable();
au0828 is changed to use v4l_enable_media_tuner() to check for
tuner availability from vidioc_g_tuner(), and au0828_v4l2_close(),
before changing tuner settings. If tuner isn't free, return busy
condition from vidioc_g_tuner() and in au0828_v4l2_close() tuner
is left untouched without powering down to save energy.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-video.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
@@ -1010,8 +1010,12 @@ static int au0828_v4l2_close(struct file *filp)gotoend;if(dev->users==1){-/* Save some power by putting tuner to sleep */-v4l2_device_call_all(&dev->v4l2_dev,0,core,s_power,0);+/* Save some power by putting tuner to sleep, if it is free */+/* What happens when radio is using tuner?? */+ret=v4l_enable_media_tuner(vdev);+if(ret==0)+v4l2_device_call_all(&dev->v4l2_dev,0,core,+s_power,0);dev->std_set_in_tuner_core=0;/* When close the device, set the usb intf0 into alt0 to free
@@ -1412,10 +1416,16 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audiostaticintvidioc_g_tuner(structfile*file,void*priv,structv4l2_tuner*t){structau0828_dev*dev=video_drvdata(file);+structvideo_device*vfd=video_devdata(file);+intret;if(t->index!=0)return-EINVAL;+ret=v4l_enable_media_tuner(vfd);+if(ret)+returnret;+dprintk(1,"%s called std_set %d dev_state %d\n",__func__,dev->std_set_in_tuner_core,dev->dev_state);
au0828 registers entity_notify hook to create media graph for
the device. This handler runs whenvere a new entity gets added
to the media device. It creates necessary links from video, vbi,
and ALSA entities to decoder and links tuner and decoder entities.
As this handler runs as entities get added, it has to maintain
state on the links it already created. New fields are added to
au0828_dev to keep this state information. entity_notify gets
unregistered before media_device unregister.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-core.c | 104 +++++++++++++++++++++++----------
drivers/media/usb/au0828/au0828.h | 6 ++
2 files changed, 78 insertions(+), 32 deletions(-)
@@ -263,11 +265,16 @@ static int au0828_create_media_graph(struct au0828_dev *dev)structmedia_device*mdev=dev->media_dev;structmedia_entity*entity;structmedia_entity*tuner=NULL,*decoder=NULL;+structmedia_entity*audio_capture=NULL;inti,ret;if(!mdev)return0;+if(dev->tuner_linked&&dev->vdev_linked&&dev->vbi_linked&&+dev->audio_capture_linked)+return0;+media_device_for_each_entity(entity,mdev){switch(entity->function){caseMEDIA_ENT_F_TUNER:
@@ -276,6 +283,9 @@ static int au0828_create_media_graph(struct au0828_dev *dev)caseMEDIA_ENT_F_ATV_DECODER:decoder=entity;break;+caseMEDIA_ENT_F_AUDIO_CAPTURE:+audio_capture=entity;+break;}}
@@ -285,60 +295,77 @@ static int au0828_create_media_graph(struct au0828_dev *dev)if(!decoder)return-EINVAL;-if(tuner){+if(tuner&&!dev->tuner_linked){+dev->tuner=tuner;ret=media_create_pad_link(tuner,TUNER_PAD_IF_OUTPUT,decoder,0,MEDIA_LNK_FL_ENABLED);if(ret)returnret;+dev->tuner_linked=1;}-if(dev->vdev.entity.graph_obj.mdev){+if(dev->vdev.entity.graph_obj.mdev&&!dev->vdev_linked){ret=media_create_pad_link(decoder,AU8522_PAD_VID_OUT,&dev->vdev.entity,0,MEDIA_LNK_FL_ENABLED);if(ret)returnret;+dev->vdev_linked=1;}-if(dev->vbi_dev.entity.graph_obj.mdev){+if(dev->vbi_dev.entity.graph_obj.mdev&&!dev->vbi_linked){ret=media_create_pad_link(decoder,AU8522_PAD_VBI_OUT,&dev->vbi_dev.entity,0,MEDIA_LNK_FL_ENABLED);if(ret)returnret;-}--for(i=0;i<AU0828_MAX_INPUT;i++){-structmedia_entity*ent=&dev->input_ent[i];+dev->vbi_linked=1;-if(!ent->graph_obj.mdev)-continue;+/*+*Inputentitiesareregisteredbeforevbientity,+*creategraphnodesforthemaftervbiiscreated+*/+for(i=0;i<AU0828_MAX_INPUT;i++){+structmedia_entity*ent=&dev->input_ent[i];-if(AUVI_INPUT(i).type==AU0828_VMUX_UNDEFINED)-break;+if(!ent->graph_obj.mdev)+continue;-switch(AUVI_INPUT(i).type){-caseAU0828_VMUX_CABLE:-caseAU0828_VMUX_TELEVISION:-caseAU0828_VMUX_DVB:-if(!tuner)+if(AUVI_INPUT(i).type==AU0828_VMUX_UNDEFINED)break;-ret=media_create_pad_link(ent,0,tuner,-TUNER_PAD_RF_INPUT,-MEDIA_LNK_FL_ENABLED);-if(ret)-returnret;-break;-caseAU0828_VMUX_COMPOSITE:-caseAU0828_VMUX_SVIDEO:-default:/* AU0828_VMUX_DEBUG */-/* FIXME: fix the decoder PAD */-ret=media_create_pad_link(ent,0,decoder,0,0);-if(ret)-returnret;-break;+switch(AUVI_INPUT(i).type){+caseAU0828_VMUX_CABLE:+caseAU0828_VMUX_TELEVISION:+caseAU0828_VMUX_DVB:+if(!tuner)+break;++ret=media_create_pad_link(ent,0,tuner,+TUNER_PAD_RF_INPUT,+MEDIA_LNK_FL_ENABLED);+if(ret)+returnret;+break;+caseAU0828_VMUX_COMPOSITE:+caseAU0828_VMUX_SVIDEO:+default:/* AU0828_VMUX_DEBUG */+/* FIXME: fix the decoder PAD */+ret=media_create_pad_link(ent,0,decoder,+0,0);+if(ret)+returnret;+break;+}}}+if(audio_capture&&!dev->audio_capture_linked){+ret=media_create_pad_link(decoder,AU8522_PAD_AUDIO_OUT,+audio_capture,0,+MEDIA_LNK_FL_ENABLED);+if(ret)+returnret;+dev->audio_capture_linked=1;+}#endifreturn0;}
@@ -349,8 +376,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,#ifdef CONFIG_MEDIA_CONTROLLERintret;-if(dev->media_dev&&-!media_devnode_is_registered(&dev->media_dev->devnode)){+if(!dev->media_dev)+return0;++if(!media_devnode_is_registered(&dev->media_dev->devnode)){/* register media device */ret=media_device_register(dev->media_dev);
Create tuner to demod pad link in disabled state to help avoid
disable step when tuner resource is requested by video or audio.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/dvb-core/dvbdev.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
@@ -593,8 +593,9 @@ int dvb_create_media_graph(struct dvb_adapter *adap)}if(tuner&&demod){+/* create tuner to demod link deactivated */ret=media_create_pad_link(tuner,TUNER_PAD_IF_OUTPUT,-demod,0,MEDIA_LNK_FL_ENABLED);+demod,0,0);if(ret)returnret;}
@@ -370,6 +370,20 @@ static int au0828_create_media_graph(struct au0828_dev *dev)return0;}+voidau0828_create_media_graph_notify(structmedia_entity*new,+void*notify_data)+{+#ifdef CONFIG_MEDIA_CONTROLLER+structau0828_dev*dev=(structau0828_dev*)notify_data;+intret;++ret=au0828_create_media_graph(dev);+if(ret)+pr_err("%s() media graph create failed for new entity %s\n",+__func__,new->name);+#endif+}+staticintau0828_enable_source(structmedia_entity*entity,structmedia_pipeline*pipe){
Create tuner to demod pad link in disabled state to help
avoid disable step when tuner resource is requested by dvb.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-core.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
@@ -297,9 +297,9 @@ static int au0828_create_media_graph(struct au0828_dev *dev)if(tuner&&!dev->tuner_linked){dev->tuner=tuner;+/* create tuner to decoder link in deactivated state */ret=media_create_pad_link(tuner,TUNER_PAD_IF_OUTPUT,-decoder,0,-MEDIA_LNK_FL_ENABLED);+decoder,0,0);if(ret)returnret;dev->tuner_linked=1;
Implements enable_source and disable_source handlers for other
drivers (v4l2-core, dvb-core, and ALSA) to use to check for
tuner connected to the decoder and activate the link if tuner
is free, and deactivate and free the tuner when it is no longer
needed.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-core.c | 148 +++++++++++++++++++++++++++++++++
drivers/media/usb/au0828/au0828.h | 2 +
2 files changed, 150 insertions(+)
@@ -370,6 +370,150 @@ static int au0828_create_media_graph(struct au0828_dev *dev)return0;}+staticintau0828_enable_source(structmedia_entity*entity,+structmedia_pipeline*pipe)+{+#ifdef CONFIG_MEDIA_CONTROLLER+structmedia_entity*source;+structmedia_entity*sink;+structmedia_link*link,*found_link=NULL;+intret=0;+structmedia_device*mdev=entity->graph_obj.mdev;+structau0828_dev*dev;++if(!mdev)+return-ENODEV;++/* for Audio and Video entities, source is the decoder */+mutex_lock(&mdev->graph_mutex);++dev=mdev->source_priv;+if(!dev->tuner||!dev->decoder){+ret=-ENODEV;+gotoend;+}++/*+*ForAudioandV4L2entity,findthelinktowhichdecoder+*isthesink.Lookforanactivelinkbetweendecoderand+*tuner,ifoneexists,nothingtodo.Ifnot,lookforany+*activelinksbetweentunerandanyotherentity.Ifone+*exists,tunerisbusy.Iftunerisfree,setuplinkand+*startpipelinefromsource(tuner).+*ForDVBFEentity,thesourceforthelinkisthetuner.+*Checkiftunerisavailableandsetuplinkandstart+*pipeline.+*/+if(entity->function!=MEDIA_ENT_F_DTV_DEMOD)+sink=dev->decoder;+else+sink=entity;++/* Is an active link between sink and tuner */+if(dev->active_link){+if(dev->active_link->sink->entity==sink&&+dev->active_link->source->entity==dev->tuner){+ret=0;+gotoend;+}else{+ret=-EBUSY;+gotoend;+}+}++list_for_each_entry(link,&sink->links,list){+/* Check sink, and source */+if(link->sink->entity==sink&&+link->source->entity==dev->tuner){+found_link=link;+break;+}+}++if(!found_link){+ret=-ENODEV;+gotoend;+}++/* activate link between source and sink and start pipeline */+source=found_link->source->entity;+ret=__media_entity_setup_link(found_link,MEDIA_LNK_FL_ENABLED);+if(ret){+pr_err(+"Activate tuner link %s->%s. Error %d\n",+source->name,sink->name,ret);+gotoend;+}++ret=__media_entity_pipeline_start(entity,pipe);+if(ret){+pr_err("Start Pipeline: %s->%s Error %d\n",+source->name,entity->name,ret);+ret=__media_entity_setup_link(found_link,0);+pr_err("Deactive link Error %d\n",ret);+gotoend;+}+/*+*saveactivelinkandactivelinkownertoavoidaudio+*deactivatingvideoownedlinkfromdisable_sourceand+*viceversa+*/+dev->active_link=found_link;+dev->active_link_owner=entity;+end:+mutex_unlock(&mdev->graph_mutex);+pr_debug("au0828_enable_source() end %s %d %d\n",+entity->name,entity->function,ret);+returnret;+#endif+return0;+}++staticvoidau0828_disable_source(structmedia_entity*entity)+{+#ifdef CONFIG_MEDIA_CONTROLLER+structmedia_entity*sink;+intret=0;+structmedia_device*mdev=entity->graph_obj.mdev;+structau0828_dev*dev;++if(!mdev)+return;++mutex_lock(&mdev->graph_mutex);+dev=mdev->source_priv;+if(!dev->tuner||!dev->decoder||!dev->active_link){+ret=-ENODEV;+gotoend;+}++if(entity->function!=MEDIA_ENT_F_DTV_DEMOD)+sink=dev->decoder;+else+sink=entity;++/* link is active - stop pipeline from source (tuner) */+if(dev->active_link&&dev->active_link->sink->entity==sink&&+dev->active_link->source->entity==dev->tuner){+/*+*preventvideofromdeactivatinglinkwhenaudio+*hasactivepipeline+*/+if(dev->active_link_owner!=entity)+gotoend;+__media_entity_pipeline_stop(entity);+ret=__media_entity_setup_link(dev->active_link,0);+if(ret)+pr_err("Deactive link Error %d\n",ret);+dev->active_link=NULL;+dev->active_link_owner=NULL;+}++end:+mutex_unlock(&mdev->graph_mutex);+#endif+}+staticintau0828_media_device_register(structau0828_dev*dev,structusb_device*udev){
@@ -400,6 +544,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,ret);returnret;}+/* set enable_source */+dev->media_dev->source_priv=(void*)dev;+dev->media_dev->enable_source=au0828_enable_source;+dev->media_dev->disable_source=au0828_disable_source;#endifreturn0;}
Media device initialization and registration is split
and there is a window between media device init and
media device register during usb probe. au0828 bridge
driver has to coordinate managed media device init and
register with snd-usb-audio. Checking if the device is
registered during media device init could result in the
two drivers stepping on each other for media init. Change
the media device init in au0828 to check if media device
dev is set as this happens at the end of media device
init in au0828 and snd-usb-audio. Change register step
in au0828 to check if media device in registered.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-core.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
@@ -229,7 +229,8 @@ static int au0828_media_device_init(struct au0828_dev *dev,if(!mdev)return-ENOMEM;-if(!media_devnode_is_registered(&mdev->devnode)){+/* check if media device is already initialized */+if(!mdev->dev){mdev->dev=&udev->dev;if(udev->product)
@@ -342,6 +343,27 @@ static int au0828_create_media_graph(struct au0828_dev *dev)return0;}+staticintau0828_media_device_register(structau0828_dev*dev,+structusb_device*udev)+{+#ifdef CONFIG_MEDIA_CONTROLLER+intret;++if(dev->media_dev&&+!media_devnode_is_registered(&dev->media_dev->devnode)){++/* register media device */+ret=media_device_register(dev->media_dev);+if(ret){+dev_err(&udev->dev,+"Media Device Register Error: %d\n",ret);+returnret;+}+}+#endif+return0;+}+staticintau0828_usb_probe(structusb_interface*interface,conststructusb_device_id*id){
@@ -469,7 +491,7 @@ static int au0828_usb_probe(struct usb_interface *interface,}#ifdef CONFIG_MEDIA_CONTROLLER-retval=media_device_register(dev->media_dev);+retval=au0828_media_device_register(dev,usbdev);#endifdone:
Change au0828 to use Managed Media Controller API to coordinate
creating/deleting media device on parent usb device it shares
with the snd-usb-audio driver. With this change, au0828 uses
media_device_get_devres() to allocate a new media device devres
or return an existing one, if it finds one.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-core.c | 44 +++++++++++++++++-----------------
1 file changed, 22 insertions(+), 22 deletions(-)
@@ -225,29 +225,29 @@ static int au0828_media_device_init(struct au0828_dev *dev,structmedia_device*mdev;intret;-mdev=kzalloc(sizeof(*mdev),GFP_KERNEL);+mdev=media_device_get_devres(&udev->dev);if(!mdev)return-ENOMEM;-mdev->dev=&udev->dev;--if(!dev->board.name)-strlcpy(mdev->model,"unknown au0828",sizeof(mdev->model));-else-strlcpy(mdev->model,dev->board.name,sizeof(mdev->model));-if(udev->serial)-strlcpy(mdev->serial,udev->serial,sizeof(mdev->serial));-strcpy(mdev->bus_info,udev->devpath);-mdev->hw_revision=le16_to_cpu(udev->descriptor.bcdDevice);-mdev->driver_version=LINUX_VERSION_CODE;--ret=media_device_init(mdev);-if(ret){-pr_err(-"Couldn't create a media device. Error: %d\n",-ret);-kfree(mdev);-returnret;+if(!media_devnode_is_registered(&mdev->devnode)){+mdev->dev=&udev->dev;++if(udev->product)+strlcpy(mdev->model,udev->product,+sizeof(mdev->model));+if(udev->serial)+strlcpy(mdev->serial,udev->serial,+sizeof(mdev->serial));+strcpy(mdev->bus_info,udev->devpath);+mdev->hw_revision=le16_to_cpu(udev->descriptor.bcdDevice);++ret=media_device_init(mdev);+if(ret){+dev_err(&udev->dev,+"Couldn't create a media device. Error: %d\n",+ret);+returnret;+}}dev->media_dev=mdev;
From: Mauro Carvalho Chehab <redacted>
Declare the interface types to be used on alsa for the new
G_TOPOLOGY ioctl.
Signed-off-by: Mauro Carvalho Chehab <redacted>
---
drivers/media/media-entity.c | 12 ++++++++++++
include/uapi/linux/media.h | 8 ++++++++
2 files changed, 20 insertions(+)
Add a range check to not let the stream_count become negative.
Wthout this check, calls to stop pipeline when there is no active
pipeline will result in stream_count < 0 condition and lock and
preventing link state (activate/deactivate) changes. This will
happen from error leg in start pipeline interface.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/media-entity.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
@@ -464,9 +464,12 @@ error:media_entity_graph_walk_start(graph,entity_err);while((entity_err=media_entity_graph_walk_next(graph))){-entity_err->stream_count--;-if(entity_err->stream_count==0)-entity_err->pipe=NULL;+/* don't let the stream_count go negative */+if(entity->stream_count>0){+entity_err->stream_count--;+if(entity_err->stream_count==0)+entity_err->pipe=NULL;+}/**Wehaven'tincreasedstream_countfurtherthanthis
@@ -498,9 +501,12 @@ void media_entity_pipeline_stop(struct media_entity *entity)media_entity_graph_walk_start(graph,entity);while((entity=media_entity_graph_walk_next(graph))){-entity->stream_count--;-if(entity->stream_count==0)-entity->pipe=NULL;+/* don't let the stream_count go negative */+if(entity->stream_count>0){+entity->stream_count--;+if(entity->stream_count==0)+entity->pipe=NULL;+}}if(!--pipe->streaming_count)
Change au0828-core to use au8522_media_pads enum defines
instead of hard-coding the pad values when it creates
media graph linking decode pads to other entities.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-core.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
Add a new v4l_vb2q_enable_media_tuner() wrapper function
to be called from v4l2-core to enable the media tuner with
videobuf2 queue, when the calling frunction has the videobuf2
queue and doesn't have the struct video_device associated with
the queue handy as in the case of vb2_core_streamon(). This
function simply calls v4l_enable_media_tuner() passing in the
pointer to struct video_device.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/v4l2-core/v4l2-dev.c | 21 +++++++++++++++++++++
include/media/v4l2-dev.h | 1 +
2 files changed, 22 insertions(+)
Add non-locking __media_entity_pipeline_start/stop() interfaces
to be called from code paths that hold the graph_mutex. For this
change, the media_entity_pipeline_start() routine is renamed to
__media_entity_pipeline_start() minus the graph_mutex lock and
unlock. media_entity_pipeline_start() now calls the non-locking
__media_entity_pipeline_start() holding the graph_lock. The stop
interface, media_entity_pipeline_stop() routine is renamed to
__media_entity_pipeline_stop() minus the graph_mutex lock and
unlock. media_entity_pipeline_stop() now calls the non-locking
__media_entity_pipeline_stop() holding the graph_lock.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/media-entity.c | 34 ++++++++++++++++++++++++----------
include/media/media-entity.h | 12 ++++++++++++
2 files changed, 36 insertions(+), 10 deletions(-)
Move the au8522_media_pads enum to au8522.h from au8522_priv.h.
This will allow au0828-core to use these defines instead of
hard-coding the pad values when it creates media graph linking
decode pads to other entities.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/dvb-frontends/au8522.h | 7 +++++++
drivers/media/dvb-frontends/au8522_priv.h | 8 --------
2 files changed, 7 insertions(+), 8 deletions(-)
Export __media_entity_setup_link() to be used from code paths that hold
the graph_mutex.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/media-entity.c | 1 +
1 file changed, 1 insertion(+)
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 tuner entity connected to the decoder and check is it
is available or busy. If tuner 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 <redacted>
---
drivers/media/v4l2-core/v4l2-dev.c | 27 +++++++++++++++++++++++++++
include/media/v4l2-dev.h | 4 ++++
2 files changed, 31 insertions(+)
Add new interfaces to register and unregister entity_notify
hook to media device to allow drivers to take appropriate
actions when as new entities get added to the shared media
device.When a new entity is registered, all registered
entity_notify hooks are invoked to allow drivers or modules
that registered hook to take appropriate action. For example,
ALSA driver registers an entity_notify hook to parse the list
of registered entities to determine if decoder has been linked
to ALSA entity. au0828 bridge driver registers an entity_notify
hook to create media graph for the device.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/media-device.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
include/media/media-device.h | 25 ++++++++++++++++++
2 files changed, 86 insertions(+)
@@ -633,6 +641,7 @@ int __must_check 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);
@@ -680,11 +689,59 @@ int __must_check __media_device_register(struct media_device *mdev,}EXPORT_SYMBOL_GPL(__media_device_register);+/**+*media_device_register_entity_notify-Registeramediaentitynotify+*callbackwithamediadevice.Whenanewentityisregistered,all+*theregisteredmedia_entity_notifycallbacksareinvoked.+*@mdev:Themediadevice+*@nptr:Themedia_entity_notify+*/+int__must_checkmedia_device_register_entity_notify(structmedia_device*mdev,+structmedia_entity_notify*nptr)+{+spin_lock(&mdev->lock);+list_add_tail(&nptr->list,&mdev->entity_notify);+spin_unlock(&mdev->lock);+return0;+}+EXPORT_SYMBOL_GPL(media_device_register_entity_notify);++/**+*__media_device_unregister_entity_notify-Unregisteramediaentitynotify+*callbackwithamediadevice.Whenanewentityisregistered,all+*theregisteredmedia_entity_notifycallbacksareinvoked.+*@mdev:Themediadevice+*@nptr:Themedia_entity_notify+*Non-lockingversion.Shouldbecalledwithmdev->lockheld.+*/+staticvoid__media_device_unregister_entity_notify(structmedia_device*mdev,+structmedia_entity_notify*nptr)+{+list_del(&nptr->list);+}++/**+*media_device_unregister_entity_notify-Unregisteramediaentitynotify+*callbackwithamediadevice.Whenanewentityisregistered,all+*theregisteredmedia_entity_notifycallbacksareinvoked.+*@mdev:Themediadevice+*@nptr:Themedia_entity_notify+*/+voidmedia_device_unregister_entity_notify(structmedia_device*mdev,+structmedia_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);+voidmedia_device_unregister(structmedia_device*mdev){structmedia_entity*entity;structmedia_entity*next;structmedia_interface*intf,*tmp_intf;+structmedia_entity_notify*notify,*nextp;if(mdev==NULL)return;
@@ -701,6 +758,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){
@@ -319,6 +325,9 @@ struct media_device {structlist_headpads;structlist_headlinks;+/* notify callback list invoked when a new entity is registered */+structlist_headentity_notify;+/* Protects the graph objects creation/removal */spinlock_tlock;/* Serializes graph operations. */
@@ -497,6 +506,11 @@ int __must_check media_device_register_entity(struct media_device *mdev,*/voidmedia_device_unregister_entity(structmedia_entity*entity);+int__must_checkmedia_device_register_entity_notify(structmedia_device*mdev,+structmedia_entity_notify*nptr);+voidmedia_device_unregister_entity_notify(structmedia_device*mdev,+structmedia_entity_notify*nptr);+/***media_device_get_devres()-getmediadeviceasdeviceresource*createsifonedoesn'texist
@@ -552,6 +566,17 @@ static inline int media_device_register_entity(struct media_device *mdev,staticinlinevoidmedia_device_unregister_entity(structmedia_entity*entity){}+staticinlineintmedia_device_register_entity_notify(+structmedia_device*mdev,+structmedia_entity_notify*nptr)+{+return0;+}+staticinlinevoidmedia_device_unregister_entity_notify(+structmedia_device*mdev,+structmedia_entity_notify*nptr)+{+}staticinlinestructmedia_device*media_device_get_devres(structdevice*dev){returnNULL;
Change au0828_unregister_media_device() to check media
device media device unregister is in progress and avoid
calling media_device_unregister() and other cleanup done
in au0828_unregister_media_device().
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-core.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
Change au0828_create_media_graph() to create pad link
between MEDIA_ENT_F_AUDIO_MIXER entity and decoder's
AU8522_PAD_AUDIO_OUT. With mixer entity now linked to
decoder, change to link MEDIA_ENT_F_AUDIO_CAPTURE to
mixer's source pad.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-core.c | 17 ++++++++++++++---
drivers/media/usb/au0828/au0828.h | 1 +
2 files changed, 15 insertions(+), 3 deletions(-)
Change to release media resources for pcm streams
and mixer before snd_card_disconnect() is done from
usb_audio_disconnect(). The stream and mixer resource
release interfaces access managed media resources
(device resources) created on the usb device parent.
These interfaces should be called before the last
put_device() which releases all the device resources.
In addition, changed the stream and mixer resource
release interfaces to check if media device unregister
is in progress and avoid calling Media Controller API
to unregister entities and remove devnodes. Media device
unregister takes care of all of this. This fixes the
the general protection faults while snd-usb-audio was
cleaning up media resources for pcm streams and mixers.
Signed-off-by: Shuah Khan <redacted>
---
sound/usb/card.c | 8 ++++++--
sound/usb/media.c | 41 +++++++++++++++++++++++++++++++----------
sound/usb/media.h | 4 ++--
sound/usb/stream.c | 1 -
4 files changed, 39 insertions(+), 15 deletions(-)
Add support to track media device unregister in progress
state to prevent more than one driver entering unregister.
This enables fixing the general protection faults while
snd-usb-audio was cleaning up media resources for pcm
streams and mixers. In this patch a new interface is added
to return the unregister in progress state. Subsequent
patches to snd-usb-audio and au0828-core use this interface
to avoid entering unregister and attempting to unregister
entities and remove devnodes while unregister is in progress.
Media device unregister removes entities and interface nodes.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/media-device.c | 5 ++++-
include/media/media-device.h | 17 +++++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
@@ -749,10 +749,13 @@ void media_device_unregister(struct media_device *mdev)spin_lock(&mdev->lock);/* Check if mdev was ever registered at all */-if(!media_devnode_is_registered(&mdev->devnode)){+/* check if unregister is in progress */+if(!media_devnode_is_registered(&mdev->devnode)||+mdev->unregister_in_progress){spin_unlock(&mdev->lock);return;}+mdev->unregister_in_progress=true;/* Remove all entities from the media device */list_for_each_entry_safe(entity,next,&mdev->entities,graph_obj.list)
@@ -332,6 +332,10 @@ struct media_device {spinlock_tlock;/* Serializes graph operations. */structmutexgraph_mutex;+/* Tracks unregister in progress state to prevent+*morethanonedriverenteringunregister+*/+boolunregister_in_progress;/* Handlers to find source entity for the sink entity and*checkifitisavailable,andactivatethelinkusing
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 need to run these handlers. The enable_source handler
finds source entity for the passed in entity and check if it is
available, and activate the link using __media_entity_setup_link()
interface. Bridge driver is expected to implement and set these
handlers and private data when media_device is registered or when
bridge driver finds the media_device during probe. This is to enable
the use-case to find tuner entity connected to the decoder entity and
check if it is available, and activate it and start pipeline between
the source and the entity. The disable_source handler deactivates the
link and stops the pipeline. This handler can be invoked from the
media core (v4l-core, dvb-core) as well as other drivers such as ALSA
that control the media device.
Signed-off-by: Shuah Khan <redacted>
---
include/media/media-device.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
entity_notify handlers are removed from media_device_unregister().
There is no need to call media_device_unregister_entity_notify()
to do that right before calling media_device_unregister().
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-core.c | 2 --
1 file changed, 2 deletions(-)
Change ALSA driver to use Managed Media Managed Controller
API to share tuner with DVB and V4L2 drivers that control
AU0828 media device. Media device is created based on a
newly added field value in the struct snd_usb_audio_quirk.
Using this approach, the media controller API usage can be
added for a specific device. In this patch, Media Controller
API is enabled for AU0828 hw. snd_usb_create_quirk() will
check this new field, if set will create a media device using
media_device_get_devres() interface.
media_device_get_devres() will allocate a new media device
devres or return an existing one, if it finds one.
During probe, media usb driver could have created the media
device devres. It will then initialze (if necessary) and
register the media device if it isn't already initialized
and registered. Media device unregister is done from
usb_audio_disconnect().
During probe, media usb driver could have created the
media device devres. It will then register the media
device if it isn't already registered. Media device
unregister is done from usb_audio_disconnect().
New structure media_ctl is added to group the new
fields to support media entity and links. This new
structure is added to struct snd_usb_substream.
A new entity_notify hook and a new ALSA capture media
entity are registered from snd_usb_pcm_open() after
setting up hardware information for the PCM device.
When a new entity is registered, Media Controller API
interface media_device_register_entity() invokes all
registered entity_notify hooks for the media device.
ALSA entity_notify hook parses all the entity list to
find a link from decoder it ALSA entity. This indicates
that the bridge driver created a link from decoder to
ALSA capture entity.
ALSA will attempt to enable the tuner to link the tuner
to the decoder calling enable_source handler if one is
provided by the bridge driver prior to starting Media
pipeline from snd_usb_hw_params(). If enable_source returns
with tuner busy condition, then snd_usb_hw_params() will fail
with -EBUSY. Media pipeline is stopped from snd_usb_hw_free().
Signed-off-by: Shuah Khan <redacted>
---
sound/usb/Makefile | 15 +++-
sound/usb/card.c | 7 ++
sound/usb/card.h | 1 +
sound/usb/media.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++
sound/usb/media.h | 54 ++++++++++++
sound/usb/pcm.c | 26 ++++--
sound/usb/quirks-table.h | 1 +
sound/usb/quirks.c | 9 +-
sound/usb/stream.c | 2 +
sound/usb/usbaudio.h | 1 +
10 files changed, 323 insertions(+), 7 deletions(-)
create mode 100644 sound/usb/media.c
create mode 100644 sound/usb/media.h
@@ -544,13 +545,19 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,[QUIRK_AUDIO_ALIGN_TRANSFER]=create_align_transfer_quirk,[QUIRK_AUDIO_STANDARD_MIXER]=create_standard_mixer_quirk,};+intret;+if(quirk->media_device){+/* don't want to fail when media_device_create() fails */+media_device_create(chip,iface);+}if(quirk->type<QUIRK_TYPE_COUNT){-returnquirk_funcs[quirk->type](chip,iface,driver,quirk);+ret=quirk_funcs[quirk->type](chip,iface,driver,quirk);}else{usb_audio_err(chip,"invalid quirk type %d\n",quirk->type);return-ENXIO;}+returnret;}/*
Add support for creating MEDIA_ENT_F_AUDIO_MIXER entity for
each mixer and a MEDIA_INTF_T_ALSA_CONTROL control interface
entity that links to mixer entities. MEDIA_INTF_T_ALSA_CONTROL
entity corresponds to the control device for the card.
Signed-off-by: Shuah Khan <redacted>
---
sound/usb/card.c | 5 +++
sound/usb/media.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++
sound/usb/media.h | 21 ++++++++++++
sound/usb/mixer.h | 1 +
sound/usb/usbaudio.h | 1 +
5 files changed, 118 insertions(+)
@@ -562,6 +562,9 @@ static int usb_audio_probe(struct usb_interface *intf,if(err<0)goto__error;+/* Create media entities for mixer and control dev */+media_mixer_init(chip);+usb_chip[chip->index]=chip;chip->num_interfaces++;usb_set_intfdata(intf,chip);
@@ -2,6 +2,18 @@# Makefile for ALSA#+# Media Controller+ifeq ($(CONFIG_MEDIA_CONTROLLER),y)+ ifeq ($(CONFIG_MEDIA_SUPPORT),y)+KBUILD_CFLAGS+=-DUSE_MEDIA_CONTROLLER+ endif+ ifeq ($(CONFIG_MEDIA_SUPPORT_MODULE),y)+ ifeq ($(MODULE),y)+KBUILD_CFLAGS+=-DUSE_MEDIA_CONTROLLER+ endif+ endif+endif
Can't we define this rather via Kconfig?
Doing this in Makefile is way too tricky, and it's unclear to users
whether MC is actually enabled or not.
Yeah doing this in Makefile is a bit tricky
and can lead to confusion.
I can't think of any specific reason why I added
this check to the Makefile instead of Kconfig.
Looks like I added this in my second version
of the patch series several months ago and didn't
revisit. I will add this to Kconfig.
I believe we can get rid of many include files just for MC support...
quoted
+#ifdef USE_MEDIA_CONTROLLER
This ifdef can be removed once if we build this object file
conditionally in Makefile.
Right.
quoted
@@ -1232,7 +1244,10 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) subs->dsd_dop.channel = 0; subs->dsd_dop.marker = 1;- return setup_hw_info(runtime, subs);+ ret = setup_hw_info(runtime, subs);+ if (ret == 0)+ ret = media_stream_init(subs, as->pcm, direction);
Need to call snd_usb_autosuspend() in the error path.
I will add it.
quoted
--- a/sound/usb/quirks.c+++ b/sound/usb/quirks.c
@@ -544,13 +545,19 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,[QUIRK_AUDIO_ALIGN_TRANSFER]=create_align_transfer_quirk,[QUIRK_AUDIO_STANDARD_MIXER]=create_standard_mixer_quirk,};+intret;+if(quirk->media_device){+/* don't want to fail when media_device_create() fails */+media_device_create(chip,iface);+}
So far, so good...
quoted
if (quirk->type < QUIRK_TYPE_COUNT) {- return quirk_funcs[quirk->type](chip, iface, driver, quirk);+ ret = quirk_funcs[quirk->type](chip, iface, driver, quirk); } else { usb_audio_err(chip, "invalid quirk type %d\n", quirk->type); return -ENXIO; }+ return ret;
Any reason to change this?
Thanks for catching this. I think I might have
added some debug code to print ret value and
missed it when I cleaned up the debug code.
I will fix it.
thanks,
-- Shuah
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org | (970) 217-8978
Em Wed, 6 Jan 2016 13:26:50 -0700
Shuah Khan [off-list ref] escreveu:
quoted hunk
From: Mauro Carvalho Chehab <redacted>
Declare the interface types to be used on alsa for the new
G_TOPOLOGY ioctl.
Signed-off-by: Mauro Carvalho Chehab <redacted>
---
drivers/media/media-entity.c | 12 ++++++++++++
include/uapi/linux/media.h | 8 ++++++++
2 files changed, 20 insertions(+)
++/* * 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 * with the legacy v1 API.The number range is out of range by purpose:
Em Wed, 6 Jan 2016 13:26:52 -0700
Shuah Khan [off-list ref] escreveu:
quoted hunk
Add new interfaces to register and unregister entity_notify
hook to media device to allow drivers to take appropriate
actions when as new entities get added to the shared media
device.When a new entity is registered, all registered
entity_notify hooks are invoked to allow drivers or modules
that registered hook to take appropriate action. For example,
ALSA driver registers an entity_notify hook to parse the list
of registered entities to determine if decoder has been linked
to ALSA entity. au0828 bridge driver registers an entity_notify
hook to create media graph for the device.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/media-device.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
include/media/media-device.h | 25 ++++++++++++++++++
2 files changed, 86 insertions(+)
@@ -633,6 +641,7 @@ int __must_check 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);
@@ -680,11 +689,59 @@ int __must_check __media_device_register(struct media_device *mdev,}EXPORT_SYMBOL_GPL(__media_device_register);+/**+*media_device_register_entity_notify-Registeramediaentitynotify+*callbackwithamediadevice.Whenanewentityisregistered,all+*theregisteredmedia_entity_notifycallbacksareinvoked.+*@mdev:Themediadevice+*@nptr:Themedia_entity_notify+*/
Please put the documentation only at the header files. Please mention that
it locks the addition using the mdev->lock spinlock.
Also, please follow the format that we're using with other KernelDoc
tags:
/**
* function() - short description
*
* @foo: foo description
* @bar: bar description
*
* detailed description
*/
In case of doubts, please check Documentation/kernel-doc-nano-HOWTO.txt.
Don't forget to check if the documentation looks sane by compiling it
with:
make cleandocs
make DOCBOOKS=device-drivers.xml htmldocs
Same applies to other documentation below and on other patches in this
series.
quoted hunk
+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);++/**+ * __media_device_unregister_entity_notify - Unregister a media entity notify+ * callback with a media device. When a new entity is registered, all+ * the registered media_entity_notify callbacks are invoked.+ * @mdev: The media device+ * @nptr: The media_entity_notify+ * Non-locking version. Should be called with mdev->lock held.+ */+static void __media_device_unregister_entity_notify(struct media_device *mdev,+ struct media_entity_notify *nptr)
__must_check
quoted hunk
+{+ list_del(&nptr->list);+}++/**+ * media_device_unregister_entity_notify - Unregister a media entity notify+ * callback with a media device. When a new entity is registered, all+ * the registered media_entity_notify callbacks are invoked.+ * @mdev: The media device+ * @nptr: The media_entity_notify+ */+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;
@@ -701,6 +758,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) {
Em Wed, 6 Jan 2016 13:26:53 -0700
Shuah Khan [off-list ref] escreveu:
quoted hunk
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 need to run these handlers. The enable_source handler
finds source entity for the passed in entity and check if it is
available, and activate the link using __media_entity_setup_link()
interface. Bridge driver is expected to implement and set these
handlers and private data when media_device is registered or when
bridge driver finds the media_device during probe. This is to enable
the use-case to find tuner entity connected to the decoder entity and
check if it is available, and activate it and start pipeline between
the source and the entity. The disable_source handler deactivates the
link and stops the pipeline. This handler can be invoked from the
media core (v4l-core, dvb-core) as well as other drivers such as ALSA
that control the media device.
Signed-off-by: Shuah Khan <redacted>
---
include/media/media-device.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
@@ -333,6 +333,25 @@ struct media_device {/* Serializes graph operations. */structmutexgraph_mutex;+/* Handlers to find source entity for the sink entity and+*checkifitisavailable,andactivatethelinkusing+*media_entity_setup_link()interfaceandstartpipeline+*fromthesourcetotheentity.+*Bridgedriverisexpectedtoimplementandsetthe+*handlerwhenmedia_deviceisregisteredorwhen+*bridgedriverfindsthemedia_deviceduringprobe.+*Bridgedriversetssource_privwithinformation+*necessarytorunenable/disablesourcehandlers.+*+*Use-case:findtunerentityconnectedtothedecoder+*entityandcheckifitisavailable,andactivatethe+*usingmedia_entity_setup_link()ifitisavailable.+*/+void*source_priv;+int(*enable_source)(structmedia_entity*entity,+structmedia_pipeline*pipe);+void(*disable_source)(structmedia_entity*entity);
Please document the new fields at the right place (Kernel-doc
comment declared before the struct).
Is this used by the media core? If so, please but the implementation
here, to make it clearer why we need those things.
quoted hunk
+ int (*link_notify)(struct media_link *link, u32 flags, unsigned int notification); };
Em Wed, 6 Jan 2016 13:26:57 -0700
Shuah Khan [off-list ref] escreveu:
quoted hunk
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 tuner entity connected to the decoder and check is it
is available or busy. If tuner 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 <redacted>
---
drivers/media/v4l2-core/v4l2-dev.c | 27 +++++++++++++++++++++++++++
include/media/v4l2-dev.h | 4 ++++
2 files changed, 31 insertions(+)
Em Wed, 6 Jan 2016 13:26:58 -0700
Shuah Khan [off-list ref] escreveu:
quoted hunk
Add a new v4l_vb2q_enable_media_tuner() wrapper function
to be called from v4l2-core to enable the media tuner with
videobuf2 queue, when the calling frunction has the videobuf2
queue and doesn't have the struct video_device associated with
the queue handy as in the case of vb2_core_streamon(). This
function simply calls v4l_enable_media_tuner() passing in the
pointer to struct video_device.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/v4l2-core/v4l2-dev.c | 21 +++++++++++++++++++++
include/media/v4l2-dev.h | 1 +
2 files changed, 22 insertions(+)
+ * have the struct video_device associated with the+ * queue handy as in the case of vb2_core_streamon(). This+ * function simply calls v4l_enable_media_tuner() passing+ * in the pointer to struct video_device.
The hole description seems confusing. I'm not seeing the light
about why this is needed.
Em Wed, 6 Jan 2016 13:27:02 -0700
Shuah Khan [off-list ref] escreveu:
au0828_create_media_graph() doesn't do any checks to determine,
if vbi_dev, vdev, and input entities have been registered prior
to creating pad links. Checking graph_obj.mdev field works as
the graph_obj.mdev field gets initialized in the entity register
interface. Fix it to check graph_obj.mdev field before creating
pad links.
@@ -291,20 +291,27 @@ static int au0828_create_media_graph(struct au0828_dev *dev)if(ret)returnret;}-ret=media_create_pad_link(decoder,AU8522_PAD_VID_OUT,-&dev->vdev.entity,0,-MEDIA_LNK_FL_ENABLED);-if(ret)-returnret;-ret=media_create_pad_link(decoder,AU8522_PAD_VBI_OUT,-&dev->vbi_dev.entity,0,-MEDIA_LNK_FL_ENABLED);-if(ret)-returnret;+if(dev->vdev.entity.graph_obj.mdev){+ret=media_create_pad_link(decoder,AU8522_PAD_VID_OUT,+&dev->vdev.entity,0,+MEDIA_LNK_FL_ENABLED);+if(ret)+returnret;+}
Those new if() doesn't look right. We can't continue if the entities
weren't registered, as the graph would have troubles. The logic should
ensure that the entities will always be created before running
au0828_create_media_graph(). If this is not the case, some async
logic is needed to ensure that.
quoted hunk
+ if (dev->vbi_dev.entity.graph_obj.mdev) {+ ret = media_create_pad_link(decoder, AU8522_PAD_VBI_OUT,+ &dev->vbi_dev.entity, 0,+ MEDIA_LNK_FL_ENABLED);+ if (ret)+ return ret;+ } for (i = 0; i < AU0828_MAX_INPUT; i++) { struct media_entity *ent = &dev->input_ent[i];+ if (!ent->graph_obj.mdev)+ continue;+ if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) break;
Em Wed, 6 Jan 2016 13:27:04 -0700
Shuah Khan [off-list ref] escreveu:
Checking for tuner availability from frontend thread start
disrupts video stream. Change to check for tuner and start
pipeline from frontend open instead and stop pipeline from
frontend release.
In addition, make a change to invoke
enable_source and disable_source handlers to check for
tuner availability. The enable_source handler finds tuner
entity connected to the decoder and check is it is available
or busy. If tuner is available, link is activated and pipeline
is started. The disable_source handler to deactivate and stop
the pipeline. dvb_enable_media_tuner() is removed as it is no
longer necessary with dvb invoking enable_source and
disable_source handlers. pipe_start_entity field is removed
and pipe field is moved to dvb_frontend from dvb_frontend_private.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/dvb-core/dvb_frontend.c | 139 +++++-----------------------------
drivers/media/dvb-core/dvb_frontend.h | 3 +
2 files changed, 24 insertions(+), 118 deletions(-)
@@ -596,104 +591,12 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe)wake_up_interruptible(&fepriv->wait_queue);}-/**-*dvb_enable_media_tuner()-triestoenabletheDVBtuner-*-*@fe:structdvb_frontendpointer-*-*Thisfunctionensuresthatjustonemediatunerisenabledforagiven-*frontend.Ithastwodifferentbehaviors:-*-Fortrivialdeviceswithjustonetuner:-*itjustenablestheexistingtuner->felink-*-Fordeviceswithmorethanonetuner:-*Itisuptothedrivertoimplementthelogicthatwillenableonetuner-*anddisabletheotherones.However,ifmorethanonetunerisenabledfor-*thesamefrontend,itwillprintanerrormessageandreturn-EINVAL.-*-*Atreturn,itwillreturntheerrorcodereturnedbymedia_entity_setup_link,-*or0ifeverythingisOK,ifnotunerislinkedtothefrontendorifthe-*mdevisNULL.-*/-#ifdef CONFIG_MEDIA_CONTROLLER_DVB-staticintdvb_enable_media_tuner(structdvb_frontend*fe)-{-structdvb_frontend_private*fepriv=fe->frontend_priv;-structdvb_adapter*adapter=fe->dvb;-structmedia_device*mdev=adapter->mdev;-structmedia_entity*entity,*source;-structmedia_link*link,*found_link=NULL;-intret,n_links=0,active_links=0;--fepriv->pipe_start_entity=NULL;--if(!mdev)-return0;--entity=fepriv->dvbdev->entity;-fepriv->pipe_start_entity=entity;--list_for_each_entry(link,&entity->links,list){-if(link->sink->entity==entity){-found_link=link;-n_links++;-if(link->flags&MEDIA_LNK_FL_ENABLED)-active_links++;-}-}--if(!n_links||active_links==1||!found_link)-return0;--/*-*Ifafrontendhasmorethanonetunerlinked,itisuptothedriver-*toselectwithonewillbetheactiveone,asthefrontendcorecan't-*guess.Ifthedriverdoesn'tdothat,itisabug.-*/-if(n_links>1&&active_links!=1){-dev_err(fe->dvb->device,-"WARNING: there are %d active links among %d tuners. This is a driver's bug!\n",-active_links,n_links);-return-EINVAL;-}--source=found_link->source->entity;-fepriv->pipe_start_entity=source;-list_for_each_entry(link,&source->links,list){-structmedia_entity*sink;-intflags=0;--sink=link->sink->entity;-if(sink==entity)-flags=MEDIA_LNK_FL_ENABLED;--ret=media_entity_setup_link(link,flags);-if(ret){-dev_err(fe->dvb->device,-"Couldn't change link %s->%s to %s. Error %d\n",-source->name,sink->name,-flags?"enabled":"disabled",-ret);-returnret;-}else-dev_dbg(fe->dvb->device,-"link %s->%s was %s\n",-source->name,sink->name,-flags?"ENABLED":"disabled");-}-return0;-}-#endif-staticintdvb_frontend_thread(void*data){structdvb_frontend*fe=data;structdvb_frontend_private*fepriv=fe->frontend_priv;enumfe_statuss;enumdvbfe_algoalgo;-#ifdef CONFIG_MEDIA_CONTROLLER_DVB-intret;-#endif-boolre_tune=false;boolsemheld=false;
@@ -706,20 +609,6 @@ static int dvb_frontend_thread(void *data)fepriv->wakeup=0;fepriv->reinitialise=0;-#ifdef CONFIG_MEDIA_CONTROLLER_DVB-ret=dvb_enable_media_tuner(fe);-if(ret){-/* FIXME: return an error if it fails */-dev_info(fe->dvb->device,-"proceeding with FE task\n");-}elseif(fepriv->pipe_start_entity){-ret=media_entity_pipeline_start(fepriv->pipe_start_entity,-&fepriv->pipe);-if(ret)-returnret;-}-#endif-dvb_frontend_init(fe);set_freezable();
Em Wed, 6 Jan 2016 13:27:06 -0700
Shuah Khan [off-list ref] escreveu:
au0828 is changed to use v4l_enable_media_tuner() to check for
tuner availability from vidioc_g_tuner(), and au0828_v4l2_close(),
before changing tuner settings. If tuner isn't free, return busy
condition from vidioc_g_tuner() and in au0828_v4l2_close() tuner
is left untouched without powering down to save energy.
Did you test the code when the input is not a tuner, but, instead,
Composite or S-Video connector, as shown at:
https://mchehab.fedorapeople.org/mc-next-gen/au0828.png
I guess calling it v4l-enable_media_tuner() is not right, specially
since there are hybrid devices that have DTV (via DVB API) and
S-Video and/or Composite/RCA capture via V4L2 API.
@@ -1010,8 +1010,12 @@ static int au0828_v4l2_close(struct file *filp)gotoend;if(dev->users==1){-/* Save some power by putting tuner to sleep */-v4l2_device_call_all(&dev->v4l2_dev,0,core,s_power,0);+/* Save some power by putting tuner to sleep, if it is free */+/* What happens when radio is using tuner?? */+ret=v4l_enable_media_tuner(vdev);+if(ret==0)+v4l2_device_call_all(&dev->v4l2_dev,0,core,+s_power,0);dev->std_set_in_tuner_core=0;/* When close the device, set the usb intf0 into alt0 to free
@@ -1412,10 +1416,16 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audiostaticintvidioc_g_tuner(structfile*file,void*priv,structv4l2_tuner*t){structau0828_dev*dev=video_drvdata(file);+structvideo_device*vfd=video_devdata(file);+intret;if(t->index!=0)return-EINVAL;+ret=v4l_enable_media_tuner(vfd);+if(ret)+returnret;+dprintk(1,"%s called std_set %d dev_state %d\n",__func__,dev->std_set_in_tuner_core,dev->dev_state);
From: One Thousand Gnomes <hidden> Date: 2016-01-28 16:09:04
On Thu, 28 Jan 2016 13:53:04 -0200
Mauro Carvalho Chehab [off-list ref] wrote:
Em Wed, 6 Jan 2016 13:27:04 -0700
Shuah Khan [off-list ref] escreveu:
quoted
Checking for tuner availability from frontend thread start
disrupts video stream. Change to check for tuner and start
pipeline from frontend open instead and stop pipeline from
frontend release.
It doesn't document all the errors you may return. Quite a lot of
kernel drivers return EBUSY when they are "single open" things.
POSIX documents certain cases that *must* error and what the error code
is. It documents certain possible failures and what their error code is.
Beyond that it's up to you.
Alan
On 01/28/2016 08:19 AM, Mauro Carvalho Chehab wrote:
Em Wed, 6 Jan 2016 13:26:53 -0700
Shuah Khan [off-list ref] escreveu:
quoted
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 need to run these handlers. The enable_source handler
finds source entity for the passed in entity and check if it is
available, and activate the link using __media_entity_setup_link()
interface. Bridge driver is expected to implement and set these
handlers and private data when media_device is registered or when
bridge driver finds the media_device during probe. This is to enable
the use-case to find tuner entity connected to the decoder entity and
check if it is available, and activate it and start pipeline between
the source and the entity. The disable_source handler deactivates the
link and stops the pipeline. This handler can be invoked from the
media core (v4l-core, dvb-core) as well as other drivers such as ALSA
that control the media device.
Signed-off-by: Shuah Khan <redacted>
---
include/media/media-device.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
@@ -333,6 +333,25 @@ struct media_device {/* Serializes graph operations. */structmutexgraph_mutex;+/* Handlers to find source entity for the sink entity and+*checkifitisavailable,andactivatethelinkusing+*media_entity_setup_link()interfaceandstartpipeline+*fromthesourcetotheentity.+*Bridgedriverisexpectedtoimplementandsetthe+*handlerwhenmedia_deviceisregisteredorwhen+*bridgedriverfindsthemedia_deviceduringprobe.+*Bridgedriversetssource_privwithinformation+*necessarytorunenable/disablesourcehandlers.+*+*Use-case:findtunerentityconnectedtothedecoder+*entityandcheckifitisavailable,andactivatethe+*usingmedia_entity_setup_link()ifitisavailable.+*/+void*source_priv;+int(*enable_source)(structmedia_entity*entity,+structmedia_pipeline*pipe);+void(*disable_source)(structmedia_entity*entity);
Please document the new fields at the right place (Kernel-doc
comment declared before the struct).
Is this used by the media core? If so, please but the implementation
here, to make it clearer why we need those things.
quoted
+ int (*link_notify)(struct media_link *link, u32 flags, unsigned int notification); };
Hi Mauro,
I don't have any problems adding documentation. I would
like to add documentation in a add-on to the patch series.
The main reason is once I add documentation to this patch,
the rest of the patches on this file don't apply and require
rebase and rework. I went though a couple of rounds of this
while you were adding documentation to the interfaces you
added.
How about I add the documentation patches at the end of
the patch series? I am concerned that rebasing for the
documentation changes will introduce bugs. Are you okay
with this proposal?
thanks,
-- Shuah
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978
Em Wed, 6 Jan 2016 13:27:09 -0700
Shuah Khan [off-list ref] escreveu:
au0828 registers entity_notify hook to create media graph for
the device. This handler runs whenvere a new entity gets added
typo: whenever.
to the media device. It creates necessary links from video, vbi,
and ALSA entities to decoder and links tuner and decoder entities.
As this handler runs as entities get added, it has to maintain
state on the links it already created. New fields are added to
au0828_dev to keep this state information. entity_notify gets
unregistered before media_device unregister.
Bty, please avoid long paragraphs at the patch description,
and please try to be clearer on your patch descriptions... That
makes boring to read everything. :-;
@@ -263,11 +265,16 @@ static int au0828_create_media_graph(struct au0828_dev *dev)structmedia_device*mdev=dev->media_dev;structmedia_entity*entity;structmedia_entity*tuner=NULL,*decoder=NULL;+structmedia_entity*audio_capture=NULL;inti,ret;if(!mdev)return0;+if(dev->tuner_linked&&dev->vdev_linked&&dev->vbi_linked&&+dev->audio_capture_linked)+return0;+media_device_for_each_entity(entity,mdev){switch(entity->function){caseMEDIA_ENT_F_TUNER:
@@ -276,6 +283,9 @@ static int au0828_create_media_graph(struct au0828_dev *dev)caseMEDIA_ENT_F_ATV_DECODER:decoder=entity;break;+caseMEDIA_ENT_F_AUDIO_CAPTURE:+audio_capture=entity;+break;}}
@@ -285,60 +295,77 @@ static int au0828_create_media_graph(struct au0828_dev *dev)if(!decoder)return-EINVAL;-if(tuner){+if(tuner&&!dev->tuner_linked){+dev->tuner=tuner;ret=media_create_pad_link(tuner,TUNER_PAD_IF_OUTPUT,decoder,0,MEDIA_LNK_FL_ENABLED);if(ret)returnret;+dev->tuner_linked=1;}-if(dev->vdev.entity.graph_obj.mdev){+if(dev->vdev.entity.graph_obj.mdev&&!dev->vdev_linked){ret=media_create_pad_link(decoder,AU8522_PAD_VID_OUT,&dev->vdev.entity,0,MEDIA_LNK_FL_ENABLED);if(ret)returnret;+dev->vdev_linked=1;}-if(dev->vbi_dev.entity.graph_obj.mdev){+if(dev->vbi_dev.entity.graph_obj.mdev&&!dev->vbi_linked){ret=media_create_pad_link(decoder,AU8522_PAD_VBI_OUT,&dev->vbi_dev.entity,0,MEDIA_LNK_FL_ENABLED);if(ret)returnret;-}--for(i=0;i<AU0828_MAX_INPUT;i++){-structmedia_entity*ent=&dev->input_ent[i];+dev->vbi_linked=1;-if(!ent->graph_obj.mdev)-continue;+/*+*Inputentitiesareregisteredbeforevbientity,+*creategraphnodesforthemaftervbiiscreated+*/+for(i=0;i<AU0828_MAX_INPUT;i++){+structmedia_entity*ent=&dev->input_ent[i];-if(AUVI_INPUT(i).type==AU0828_VMUX_UNDEFINED)-break;+if(!ent->graph_obj.mdev)+continue;-switch(AUVI_INPUT(i).type){-caseAU0828_VMUX_CABLE:-caseAU0828_VMUX_TELEVISION:-caseAU0828_VMUX_DVB:-if(!tuner)+if(AUVI_INPUT(i).type==AU0828_VMUX_UNDEFINED)break;-ret=media_create_pad_link(ent,0,tuner,-TUNER_PAD_RF_INPUT,-MEDIA_LNK_FL_ENABLED);-if(ret)-returnret;-break;-caseAU0828_VMUX_COMPOSITE:-caseAU0828_VMUX_SVIDEO:-default:/* AU0828_VMUX_DEBUG */-/* FIXME: fix the decoder PAD */-ret=media_create_pad_link(ent,0,decoder,0,0);-if(ret)-returnret;-break;+switch(AUVI_INPUT(i).type){+caseAU0828_VMUX_CABLE:+caseAU0828_VMUX_TELEVISION:+caseAU0828_VMUX_DVB:+if(!tuner)+break;++ret=media_create_pad_link(ent,0,tuner,+TUNER_PAD_RF_INPUT,+MEDIA_LNK_FL_ENABLED);+if(ret)+returnret;+break;+caseAU0828_VMUX_COMPOSITE:+caseAU0828_VMUX_SVIDEO:+default:/* AU0828_VMUX_DEBUG */+/* FIXME: fix the decoder PAD */+ret=media_create_pad_link(ent,0,decoder,+0,0);+if(ret)+returnret;+break;+}}}+if(audio_capture&&!dev->audio_capture_linked){+ret=media_create_pad_link(decoder,AU8522_PAD_AUDIO_OUT,+audio_capture,0,+MEDIA_LNK_FL_ENABLED);+if(ret)+returnret;+dev->audio_capture_linked=1;+}#endifreturn0;}
@@ -349,8 +376,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,#ifdef CONFIG_MEDIA_CONTROLLERintret;-if(dev->media_dev&&-!media_devnode_is_registered(&dev->media_dev->devnode)){+if(!dev->media_dev)+return0;++if(!media_devnode_is_registered(&dev->media_dev->devnode)){/* register media device */ret=media_device_register(dev->media_dev);
Hmm... now I understood why you did the changes on patch 13/31.
I see what you're doing, but not sure if this is a good idea
to have one bool for each possible device. On au0828, the
topology is actually simpler than on other devices, as it
currently supports a very few set of I2C devices, but on other
drivers, things can be messier.
See, for example, two graphs for em28xx-based devices:
https://mchehab.fedorapeople.org/mc-next-gen/wintv_usb2.pnghttps://mchehab.fedorapeople.org/mc-next-gen/hvr_950.png
On the first graph, the tuner is not connected directly to the
analog demod, but, instead, to two other elements:
- tda9887 - for video
- msp3400 - for audio
IMHO, the best way to handle graph setup is that each driver
should handle the links that belong only to them synchronously,
after creating/registering all the entities.
So, only the links between two drivers would be asynchronously
created. So, In the case of au0828:
- au0828 core will create the connector entities;
- I2C drivers will create their own entities;
- DVB core will create the DVB entities/interfaces;
- V4L core will create V4L interfaces and I/O entities;
- au0828 V4L driver will create all V4L links, after
ensuring that the needed I2C drivers were bound;
- snd-usb-audio will create all ALSA-specific entities links;
The V4L->ALSA links will either be created by au0828-core,
via the notification handler.
With that in mind, I don't see any need to touch at
au0828_create_media_graph(). It will need an extra function
to handle the notification when ALSA gets registered
(or when the entities there are added, whatever works best).
Regards,
Mauro
Em Wed, 6 Jan 2016 13:27:11 -0700
Shuah Khan [off-list ref] escreveu:
quoted hunk
Create tuner to demod pad link in disabled state to help avoid
disable step when tuner resource is requested by video or audio.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/dvb-core/dvbdev.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
@@ -593,8 +593,9 @@ int dvb_create_media_graph(struct dvb_adapter *adap)}if(tuner&&demod){+/* create tuner to demod link deactivated */ret=media_create_pad_link(tuner,TUNER_PAD_IF_OUTPUT,-demod,0,MEDIA_LNK_FL_ENABLED);+demod,0,0);
This is not right, as it makes no sense for DVB-only drivers.
Em Wed, 6 Jan 2016 13:27:12 -0700
Shuah Khan [off-list ref] escreveu:
quoted hunk
Implements enable_source and disable_source handlers for other
drivers (v4l2-core, dvb-core, and ALSA) to use to check for
tuner connected to the decoder and activate the link if tuner
is free, and deactivate and free the tuner when it is no longer
needed.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-core.c | 148 +++++++++++++++++++++++++++++++++
drivers/media/usb/au0828/au0828.h | 2 +
2 files changed, 150 insertions(+)
@@ -370,6 +370,150 @@ static int au0828_create_media_graph(struct au0828_dev *dev)return0;}+staticintau0828_enable_source(structmedia_entity*entity,+structmedia_pipeline*pipe)+{
The best would be to put those enable source stuff at the core, in a way
that other drivers could share it.
Not sure about the implementation, as this requires testing ;)
Did you consider the cases where the source connector is S-Video
or Composite?
quoted hunk
+#ifdef CONFIG_MEDIA_CONTROLLER+ struct media_entity *source;+ struct media_entity *sink;+ struct media_link *link, *found_link = NULL;+ int ret = 0;+ struct media_device *mdev = entity->graph_obj.mdev;+ struct au0828_dev *dev;++ if (!mdev)+ return -ENODEV;++ /* for Audio and Video entities, source is the decoder */+ mutex_lock(&mdev->graph_mutex);++ dev = mdev->source_priv;+ if (!dev->tuner || !dev->decoder) {+ ret = -ENODEV;+ goto end;+ }++ /*+ * For Audio and V4L2 entity, find the link to which decoder+ * is the sink. Look for an active link between decoder and+ * tuner, if one exists, nothing to do. If not, look for any+ * active links between tuner and any other entity. If one+ * exists, tuner is busy. If tuner is free, setup link and+ * start pipeline from source (tuner).+ * For DVB FE entity, the source for the link is the tuner.+ * Check if tuner is available and setup link and start+ * pipeline.+ */+ if (entity->function != MEDIA_ENT_F_DTV_DEMOD)+ sink = dev->decoder;+ else+ sink = entity;++ /* Is an active link between sink and tuner */+ if (dev->active_link) {+ if (dev->active_link->sink->entity == sink &&+ dev->active_link->source->entity == dev->tuner) {+ ret = 0;+ goto end;+ } else {+ ret = -EBUSY;+ goto end;+ }+ }++ list_for_each_entry(link, &sink->links, list) {+ /* Check sink, and source */+ if (link->sink->entity == sink &&+ link->source->entity == dev->tuner) {+ found_link = link;+ break;+ }+ }++ if (!found_link) {+ ret = -ENODEV;+ goto end;+ }++ /* activate link between source and sink and start pipeline */+ source = found_link->source->entity;+ ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);+ if (ret) {+ pr_err(+ "Activate tuner link %s->%s. Error %d\n",+ source->name, sink->name, ret);+ goto end;+ }++ ret = __media_entity_pipeline_start(entity, pipe);+ if (ret) {+ pr_err("Start Pipeline: %s->%s Error %d\n",+ source->name, entity->name, ret);+ ret = __media_entity_setup_link(found_link, 0);+ pr_err("Deactive link Error %d\n", ret);+ goto end;+ }+ /*+ * save active link and active link owner to avoid audio+ * deactivating video owned link from disable_source and+ * vice versa+ */+ dev->active_link = found_link;+ dev->active_link_owner = entity;+end:+ mutex_unlock(&mdev->graph_mutex);+ pr_debug("au0828_enable_source() end %s %d %d\n",+ entity->name, entity->function, ret);+ return ret;+#endif+ return 0;+}++static void au0828_disable_source(struct media_entity *entity)+{+#ifdef CONFIG_MEDIA_CONTROLLER+ struct media_entity *sink;+ int ret = 0;+ struct media_device *mdev = entity->graph_obj.mdev;+ struct au0828_dev *dev;++ if (!mdev)+ return;++ mutex_lock(&mdev->graph_mutex);+ dev = mdev->source_priv;+ if (!dev->tuner || !dev->decoder || !dev->active_link) {+ ret = -ENODEV;+ goto end;+ }++ if (entity->function != MEDIA_ENT_F_DTV_DEMOD)+ sink = dev->decoder;+ else+ sink = entity;++ /* link is active - stop pipeline from source (tuner) */+ if (dev->active_link && dev->active_link->sink->entity == sink &&+ dev->active_link->source->entity == dev->tuner) {+ /*+ * prevent video from deactivating link when audio+ * has active pipeline+ */+ if (dev->active_link_owner != entity)+ goto end;+ __media_entity_pipeline_stop(entity);+ ret = __media_entity_setup_link(dev->active_link, 0);+ if (ret)+ pr_err("Deactive link Error %d\n", ret);+ dev->active_link = NULL;+ dev->active_link_owner = NULL;+ }++end:+ mutex_unlock(&mdev->graph_mutex);+#endif+}+ static int au0828_media_device_register(struct au0828_dev *dev, struct usb_device *udev) {
Em Wed, 6 Jan 2016 13:27:13 -0700
Shuah Khan [off-list ref] escreveu:
Add a new wrapper function to au0828_create_media_graph()
to be called as an entity_notify function to fix null
pointer dereference. A rebasing mistake resulted in
registering au0828_create_media_graph() without the
correct parameters which lead to the following
null pointer dereference:
[ 69.006164] Call Trace:
[ 69.006169] [<ffffffff81a9a1b0>] dump_stack+0x44/0x64
[ 69.006175] [<ffffffff81503af9>] print_trailer+0xf9/0x150
[ 69.006180] [<ffffffff81509284>] object_err+0x34/0x40
[ 69.006185] [<ffffffff815063c4>] ? ___slab_alloc+0x4c4/0x4e0
[ 69.006190] [<ffffffff8150b732>] kasan_report_error+0x212/0x520
[ 69.006196] [<ffffffff815063c4>] ? ___slab_alloc+0x4c4/0x4e0
[ 69.006201] [<ffffffff8150ba83>] __asan_report_load1_noabort+0x43/0x50
[ 69.006208] [<ffffffffa0d30991>] ? au0828_create_media_graph+0x641/0x730 [au0828]
[ 69.006215] [<ffffffffa0d30991>] au0828_create_media_graph+0x641/0x730 [au0828]
[ 69.006221] [<ffffffff82245c3d>] media_device_register_entity+0x33d/0x4f0
[ 69.006234] [<ffffffffa0ebeb1c>] media_stream_init+0x2ac/0x610 [snd_usb_audio]
[ 69.006247] [<ffffffffa0ea9a70>] snd_usb_pcm_open+0xcd0/0x1280 [snd_usb_audio]
Please merge the fix with the patch that caused the regression.
@@ -370,6 +370,20 @@ static int au0828_create_media_graph(struct au0828_dev *dev)return0;}+voidau0828_create_media_graph_notify(structmedia_entity*new,+void*notify_data)+{+#ifdef CONFIG_MEDIA_CONTROLLER+structau0828_dev*dev=(structau0828_dev*)notify_data;+intret;++ret=au0828_create_media_graph(dev);+if(ret)+pr_err("%s() media graph create failed for new entity %s\n",+__func__,new->name);+#endif+}+staticintau0828_enable_source(structmedia_entity*entity,structmedia_pipeline*pipe){
Em Wed, 6 Jan 2016 14:01:54 -0700
Shuah Khan [off-list ref] escreveu:
entity_notify handlers are removed from media_device_unregister().
There is no need to call media_device_unregister_entity_notify()
to do that right before calling media_device_unregister().
Em Wed, 6 Jan 2016 13:27:17 -0700
Shuah Khan [off-list ref] escreveu:
Change au0828_create_media_graph() to create pad link
between MEDIA_ENT_F_AUDIO_MIXER entity and decoder's
AU8522_PAD_AUDIO_OUT. With mixer entity now linked to
decoder, change to link MEDIA_ENT_F_AUDIO_CAPTURE to
mixer's source pad.
See my comments about doing only this asynchronously on the previous
patches.
Regards,
Mauro
On 01/28/2016 09:07 AM, One Thousand Gnomes wrote:
On Thu, 28 Jan 2016 13:53:04 -0200
Mauro Carvalho Chehab [off-list ref] wrote:
quoted
Em Wed, 6 Jan 2016 13:27:04 -0700
Shuah Khan [off-list ref] escreveu:
quoted
Checking for tuner availability from frontend thread start
disrupts video stream. Change to check for tuner and start
pipeline from frontend open instead and stop pipeline from
frontend release.
That's wrong, as DVB can be opened on read-only mode, where
it won't be changing anything.
Correct. Please check the code. Tuner availability check is
done when the device is opened in Write mode in the following
conditional.
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
It doesn't document all the errors you may return. Quite a lot of
kernel drivers return EBUSY when they are "single open" things.
POSIX documents certain cases that *must* error and what the error code
is. It documents certain possible failures and what their error code is.
Beyond that it's up to you.
Returning EBUSY clearly indicates the reason why the device
can't be opened in this case.
thanks,
-- Shuah
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org | (970) 217-8978
Em Wed, 6 Jan 2016 13:27:18 -0700
Shuah Khan [off-list ref] escreveu:
Add support to track media device unregister in progress
state to prevent more than one driver entering unregister.
This enables fixing the general protection faults while
snd-usb-audio was cleaning up media resources for pcm
streams and mixers. In this patch a new interface is added
to return the unregister in progress state. Subsequent
patches to snd-usb-audio and au0828-core use this interface
to avoid entering unregister and attempting to unregister
entities and remove devnodes while unregister is in progress.
Media device unregister removes entities and interface nodes.
Hmm... isn't the spinlock enough to serialize it? It seems weird the
need of an extra bool here to warrant that this is really serialized.
@@ -749,10 +749,13 @@ void media_device_unregister(struct media_device *mdev)spin_lock(&mdev->lock);/* Check if mdev was ever registered at all */-if(!media_devnode_is_registered(&mdev->devnode)){+/* check if unregister is in progress */+if(!media_devnode_is_registered(&mdev->devnode)||+mdev->unregister_in_progress){spin_unlock(&mdev->lock);return;}+mdev->unregister_in_progress=true;/* Remove all entities from the media device */list_for_each_entry_safe(entity,next,&mdev->entities,graph_obj.list)
@@ -332,6 +332,10 @@ struct media_device {spinlock_tlock;/* Serializes graph operations. */structmutexgraph_mutex;+/* Tracks unregister in progress state to prevent+*morethanonedriverenteringunregister+*/+boolunregister_in_progress;/* Handlers to find source entity for the sink entity and*checkifitisavailable,andactivatethelinkusing
On 01/28/2016 10:01 AM, Mauro Carvalho Chehab wrote:
Em Wed, 6 Jan 2016 13:27:18 -0700
Shuah Khan [off-list ref] escreveu:
quoted
Add support to track media device unregister in progress
state to prevent more than one driver entering unregister.
This enables fixing the general protection faults while
snd-usb-audio was cleaning up media resources for pcm
streams and mixers. In this patch a new interface is added
to return the unregister in progress state. Subsequent
patches to snd-usb-audio and au0828-core use this interface
to avoid entering unregister and attempting to unregister
entities and remove devnodes while unregister is in progress.
Media device unregister removes entities and interface nodes.
Hmm... isn't the spinlock enough to serialize it? It seems weird the
need of an extra bool here to warrant that this is really serialized.
The spinlock and check for media_devnode_is_registered(&mdev->devnode)
aren't enough to ensure only one driver enters the unregister. Please
note that the devnode isn't marked unregistered until the end in
media_device_unregister().
@@ -749,10 +749,13 @@ void media_device_unregister(struct media_device *mdev)spin_lock(&mdev->lock);/* Check if mdev was ever registered at all */-if(!media_devnode_is_registered(&mdev->devnode)){+/* check if unregister is in progress */+if(!media_devnode_is_registered(&mdev->devnode)||+mdev->unregister_in_progress){spin_unlock(&mdev->lock);return;}+mdev->unregister_in_progress=true;/* Remove all entities from the media device */list_for_each_entry_safe(entity,next,&mdev->entities,graph_obj.list)
@@ -332,6 +332,10 @@ struct media_device {spinlock_tlock;/* Serializes graph operations. */structmutexgraph_mutex;+/* Tracks unregister in progress state to prevent+*morethanonedriverenteringunregister+*/+boolunregister_in_progress;/* Handlers to find source entity for the sink entity and*checkifitisavailable,andactivatethelinkusing
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978
Em Wed, 6 Jan 2016 13:27:20 -0700
Shuah Khan [off-list ref] escreveu:
quoted hunk
Change au0828_unregister_media_device() to check media
device media device unregister is in progress and avoid
calling media_device_unregister() and other cleanup done
in au0828_unregister_media_device().
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-core.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
On 01/28/2016 08:13 AM, Mauro Carvalho Chehab wrote:
Em Wed, 6 Jan 2016 13:26:52 -0700
Shuah Khan [off-list ref] escreveu:
quoted
Add new interfaces to register and unregister entity_notify
hook to media device to allow drivers to take appropriate
actions when as new entities get added to the shared media
device.When a new entity is registered, all registered
entity_notify hooks are invoked to allow drivers or modules
that registered hook to take appropriate action. For example,
ALSA driver registers an entity_notify hook to parse the list
of registered entities to determine if decoder has been linked
to ALSA entity. au0828 bridge driver registers an entity_notify
hook to create media graph for the device.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/media-device.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
include/media/media-device.h | 25 ++++++++++++++++++
2 files changed, 86 insertions(+)
@@ -633,6 +641,7 @@ int __must_check 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);
@@ -680,11 +689,59 @@ int __must_check __media_device_register(struct media_device *mdev,}EXPORT_SYMBOL_GPL(__media_device_register);+/**+*media_device_register_entity_notify-Registeramediaentitynotify+*callbackwithamediadevice.Whenanewentityisregistered,all+*theregisteredmedia_entity_notifycallbacksareinvoked.+*@mdev:Themediadevice+*@nptr:Themedia_entity_notify+*/
Please put the documentation only at the header files. Please mention that
it locks the addition using the mdev->lock spinlock.
Also, please follow the format that we're using with other KernelDoc
tags:
/**
* function() - short description
*
* @foo: foo description
* @bar: bar description
*
* detailed description
*/
In case of doubts, please check Documentation/kernel-doc-nano-HOWTO.txt.
Don't forget to check if the documentation looks sane by compiling it
with:
make cleandocs
make DOCBOOKS=device-drivers.xml htmldocs
Same applies to other documentation below and on other patches in this
series.
quoted
+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);++/**+ * __media_device_unregister_entity_notify - Unregister a media entity notify+ * callback with a media device. When a new entity is registered, all+ * the registered media_entity_notify callbacks are invoked.+ * @mdev: The media device+ * @nptr: The media_entity_notify+ * Non-locking version. Should be called with mdev->lock held.+ */+static void __media_device_unregister_entity_notify(struct media_device *mdev,+ struct media_entity_notify *nptr)
__must_check
Thanks for the catch. Will fix it.
quoted
+{+ list_del(&nptr->list);+}++/**+ * media_device_unregister_entity_notify - Unregister a media entity notify+ * callback with a media device. When a new entity is registered, all+ * the registered media_entity_notify callbacks are invoked.+ * @mdev: The media device+ * @nptr: The media_entity_notify+ */+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;
@@ -701,6 +758,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) {
I would like to add documentation as an add-on to the series,
as I explained in response to [PATCH 04/31]
Hope that is okay for this patch as well.
thanks,
-- Shuah
quoted
/**
* media_device_get_devres() - get media device as device resource
* creates if one doesn't exist
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978
On 01/28/2016 08:26 AM, Mauro Carvalho Chehab wrote:
Em Wed, 6 Jan 2016 13:26:57 -0700
Shuah Khan [off-list ref] escreveu:
quoted
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 tuner entity connected to the decoder and check is it
is available or busy. If tuner 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 <redacted>
---
drivers/media/v4l2-core/v4l2-dev.c | 27 +++++++++++++++++++++++++++
include/media/v4l2-dev.h | 4 ++++
2 files changed, 31 insertions(+)
Since I am going to be adding a new source file, I can
add documentation in the same patch.
thanks,
-- Shuah
quoted
+ /* this release function frees the vdev pointer */ void video_device_release(struct video_device *vdev);
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org | (970) 217-8978
Em Thu, 28 Jan 2016 09:28:37 -0700
Shuah Khan [off-list ref] escreveu:
On 01/28/2016 08:19 AM, Mauro Carvalho Chehab wrote:
quoted
Em Wed, 6 Jan 2016 13:26:53 -0700
Shuah Khan [off-list ref] escreveu:
quoted
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 need to run these handlers. The enable_source handler
finds source entity for the passed in entity and check if it is
available, and activate the link using __media_entity_setup_link()
interface. Bridge driver is expected to implement and set these
handlers and private data when media_device is registered or when
bridge driver finds the media_device during probe. This is to enable
the use-case to find tuner entity connected to the decoder entity and
check if it is available, and activate it and start pipeline between
the source and the entity. The disable_source handler deactivates the
link and stops the pipeline. This handler can be invoked from the
media core (v4l-core, dvb-core) as well as other drivers such as ALSA
that control the media device.
Signed-off-by: Shuah Khan <redacted>
---
include/media/media-device.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
@@ -333,6 +333,25 @@ struct media_device {/* Serializes graph operations. */structmutexgraph_mutex;+/* Handlers to find source entity for the sink entity and+*checkifitisavailable,andactivatethelinkusing+*media_entity_setup_link()interfaceandstartpipeline+*fromthesourcetotheentity.+*Bridgedriverisexpectedtoimplementandsetthe+*handlerwhenmedia_deviceisregisteredorwhen+*bridgedriverfindsthemedia_deviceduringprobe.+*Bridgedriversetssource_privwithinformation+*necessarytorunenable/disablesourcehandlers.+*+*Use-case:findtunerentityconnectedtothedecoder+*entityandcheckifitisavailable,andactivatethe+*usingmedia_entity_setup_link()ifitisavailable.+*/+void*source_priv;+int(*enable_source)(structmedia_entity*entity,+structmedia_pipeline*pipe);+void(*disable_source)(structmedia_entity*entity);
Please document the new fields at the right place (Kernel-doc
comment declared before the struct).
Is this used by the media core? If so, please but the implementation
here, to make it clearer why we need those things.
quoted
+ int (*link_notify)(struct media_link *link, u32 flags, unsigned int notification); };
Hi Mauro,
I don't have any problems adding documentation. I would
like to add documentation in a add-on to the patch series.
The main reason is once I add documentation to this patch,
the rest of the patches on this file don't apply and require
rebase and rework. I went though a couple of rounds of this
while you were adding documentation to the interfaces you
added.
How about I add the documentation patches at the end of
the patch series? I am concerned that rebasing for the
documentation changes will introduce bugs. Are you okay
with this proposal?
I'm ok with that for those inlined kernel-doc stuff. On
the changes at the uapi/linux/media.h, I would prefer if
you could add the documentation together with the patch,
as it makes clearer for the reviewers. As you only
touched it on one or two patches, this won't cause any
breakages on the remaining patches.
Regards,
Mauro
Em Thu, 28 Jan 2016 10:04:24 -0700
Shuah Khan [off-list ref] escreveu:
On 01/28/2016 10:01 AM, Mauro Carvalho Chehab wrote:
quoted
Em Wed, 6 Jan 2016 13:27:18 -0700
Shuah Khan [off-list ref] escreveu:
quoted
Add support to track media device unregister in progress
state to prevent more than one driver entering unregister.
This enables fixing the general protection faults while
snd-usb-audio was cleaning up media resources for pcm
streams and mixers. In this patch a new interface is added
to return the unregister in progress state. Subsequent
patches to snd-usb-audio and au0828-core use this interface
to avoid entering unregister and attempting to unregister
entities and remove devnodes while unregister is in progress.
Media device unregister removes entities and interface nodes.
Hmm... isn't the spinlock enough to serialize it? It seems weird the
need of an extra bool here to warrant that this is really serialized.
The spinlock and check for media_devnode_is_registered(&mdev->devnode)
aren't enough to ensure only one driver enters the unregister.
Please
note that the devnode isn't marked unregistered until the end in
media_device_unregister().
I guess the call to:
device_remove_file(&mdev->devnode.dev, &dev_attr_model);
IMO, This should be, instead, at media_devnode_unregister().
Then, we can change the logic at media_devnode_unregister() to:
void media_devnode_unregister(struct media_devnode *mdev)
{
mutex_lock(&media_devnode_lock);
/* Check if mdev was ever registered at all */
if (!media_devnode_is_registered(mdev)) {
mutex_unlock(&media_devnode_lock);
return;
}
clear_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
mutex_unlock(&media_devnode_lock);
device_remove_file(&mdev->devnode.dev, &dev_attr_model);
device_unregister(&mdev->dev);
}
This sounds enough to avoid device_unregister() or device_remove_file()
to be called twice.
@@ -749,10 +749,13 @@ void media_device_unregister(struct media_device *mdev)spin_lock(&mdev->lock);/* Check if mdev was ever registered at all */-if(!media_devnode_is_registered(&mdev->devnode)){+/* check if unregister is in progress */+if(!media_devnode_is_registered(&mdev->devnode)||+mdev->unregister_in_progress){spin_unlock(&mdev->lock);return;}+mdev->unregister_in_progress=true;/* Remove all entities from the media device */list_for_each_entry_safe(entity,next,&mdev->entities,graph_obj.list)
@@ -332,6 +332,10 @@ struct media_device {spinlock_tlock;/* Serializes graph operations. */structmutexgraph_mutex;+/* Tracks unregister in progress state to prevent+*morethanonedriverenteringunregister+*/+boolunregister_in_progress;/* Handlers to find source entity for the sink entity and*checkifitisavailable,andactivatethelinkusing
On 01/28/2016 08:29 AM, Mauro Carvalho Chehab wrote:
Em Wed, 6 Jan 2016 13:26:58 -0700
Shuah Khan [off-list ref] escreveu:
quoted
Add a new v4l_vb2q_enable_media_tuner() wrapper function
to be called from v4l2-core to enable the media tuner with
videobuf2 queue, when the calling frunction has the videobuf2
queue and doesn't have the struct video_device associated with
the queue handy as in the case of vb2_core_streamon(). This
function simply calls v4l_enable_media_tuner() passing in the
pointer to struct video_device.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/v4l2-core/v4l2-dev.c | 21 +++++++++++++++++++++
include/media/v4l2-dev.h | 1 +
2 files changed, 22 insertions(+)
+ * have the struct video_device associated with the+ * queue handy as in the case of vb2_core_streamon(). This+ * function simply calls v4l_enable_media_tuner() passing+ * in the pointer to struct video_device.
The hole description seems confusing. I'm not seeing the light
about why this is needed.
Sorry if the description isn't clear. During videobuf2
work, owner field in struct vb2_queue is changed from
struct v4l2_fh * to void. Prior to this work, I could
call v4l_enable_media_tuner().
+ ret = v4l_enable_media_tuner(q->owner->vdev);
+ if (ret)
+ return ret;
As you can see with the videobuf2, to be able to call
v4l_enable_media_tuner() from vb2_core_streamon(), I have
had to this wrapper to maintain the abstraction introduced
in videobuf2 work.
Hope this helps the need for this wrapper.
thanks,
-- Shuah
/* this release function frees the vdev pointer */
void video_device_release(struct video_device *vdev);
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org | (970) 217-8978
Em Thu, 28 Jan 2016 09:59:38 -0700
Shuah Khan [off-list ref] escreveu:
On 01/28/2016 09:07 AM, One Thousand Gnomes wrote:
quoted
On Thu, 28 Jan 2016 13:53:04 -0200
Mauro Carvalho Chehab [off-list ref] wrote:
quoted
Em Wed, 6 Jan 2016 13:27:04 -0700
Shuah Khan [off-list ref] escreveu:
quoted
Checking for tuner availability from frontend thread start
disrupts video stream. Change to check for tuner and start
pipeline from frontend open instead and stop pipeline from
frontend release.
That's wrong, as DVB can be opened on read-only mode, where
it won't be changing anything.
Correct. Please check the code. Tuner availability check is
done when the device is opened in Write mode in the following
conditional.
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
OK.
Thanks!
Mauro
, I don't think POSIX allows to return an error like EBUSY
It doesn't document all the errors you may return. Quite a lot of
kernel drivers return EBUSY when they are "single open" things.
POSIX documents certain cases that *must* error and what the error code
is. It documents certain possible failures and what their error code is.
Beyond that it's up to you.
Returning EBUSY clearly indicates the reason why the device
can't be opened in this case.
thanks,
-- Shuah
Em Thu, 28 Jan 2016 10:31:21 -0700
Shuah Khan [off-list ref] escreveu:
On 01/28/2016 08:29 AM, Mauro Carvalho Chehab wrote:
quoted
Em Wed, 6 Jan 2016 13:26:58 -0700
Shuah Khan [off-list ref] escreveu:
quoted
Add a new v4l_vb2q_enable_media_tuner() wrapper function
to be called from v4l2-core to enable the media tuner with
videobuf2 queue, when the calling frunction has the videobuf2
queue and doesn't have the struct video_device associated with
the queue handy as in the case of vb2_core_streamon(). This
function simply calls v4l_enable_media_tuner() passing in the
pointer to struct video_device.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/v4l2-core/v4l2-dev.c | 21 +++++++++++++++++++++
include/media/v4l2-dev.h | 1 +
2 files changed, 22 insertions(+)
+ * have the struct video_device associated with the+ * queue handy as in the case of vb2_core_streamon(). This+ * function simply calls v4l_enable_media_tuner() passing+ * in the pointer to struct video_device.
The hole description seems confusing. I'm not seeing the light
about why this is needed.
Sorry if the description isn't clear. During videobuf2
work, owner field in struct vb2_queue is changed from
struct v4l2_fh * to void. Prior to this work, I could
call v4l_enable_media_tuner().
+ ret = v4l_enable_media_tuner(q->owner->vdev);
+ if (ret)
+ return ret;
As you can see with the videobuf2, to be able to call
v4l_enable_media_tuner() from vb2_core_streamon(), I have
had to this wrapper to maintain the abstraction introduced
in videobuf2 work.
Hope this helps the need for this wrapper.
It is clearer now. Please improve the description of the patch
on the next version for us to remember ;)
Regards,
Mauro
On 01/28/2016 08:37 AM, Mauro Carvalho Chehab wrote:
Em Wed, 6 Jan 2016 13:27:02 -0700
Shuah Khan [off-list ref] escreveu:
quoted
au0828_create_media_graph() doesn't do any checks to determine,
if vbi_dev, vdev, and input entities have been registered prior
to creating pad links. Checking graph_obj.mdev field works as
the graph_obj.mdev field gets initialized in the entity register
interface. Fix it to check graph_obj.mdev field before creating
pad links.
@@ -291,20 +291,27 @@ static int au0828_create_media_graph(struct au0828_dev *dev)if(ret)returnret;}-ret=media_create_pad_link(decoder,AU8522_PAD_VID_OUT,-&dev->vdev.entity,0,-MEDIA_LNK_FL_ENABLED);-if(ret)-returnret;-ret=media_create_pad_link(decoder,AU8522_PAD_VBI_OUT,-&dev->vbi_dev.entity,0,-MEDIA_LNK_FL_ENABLED);-if(ret)-returnret;+if(dev->vdev.entity.graph_obj.mdev){+ret=media_create_pad_link(decoder,AU8522_PAD_VID_OUT,+&dev->vdev.entity,0,+MEDIA_LNK_FL_ENABLED);+if(ret)+returnret;+}
Those new if() doesn't look right. We can't continue if the entities
weren't registered, as the graph would have troubles. The logic should
ensure that the entities will always be created before running
au0828_create_media_graph(). If this is not the case, some async
logic is needed to ensure that.
There have been some changes in au0828 media init and
register sequence in 4.5-rc1. wau0828 does its graph
creation before it registers media_device.
I needed these checks before this above. It looks
like I might have simply rebased my patch over
without taking this change into account. I will
try without these checks.
Async method is already in place for snd-usb-audio
part of the graph. Please see patch 20 in the series.
thanks,
-- Shuah
quoted
+ if (dev->vbi_dev.entity.graph_obj.mdev) {+ ret = media_create_pad_link(decoder, AU8522_PAD_VBI_OUT,+ &dev->vbi_dev.entity, 0,+ MEDIA_LNK_FL_ENABLED);+ if (ret)+ return ret;+ } for (i = 0; i < AU0828_MAX_INPUT; i++) { struct media_entity *ent = &dev->input_ent[i];+ if (!ent->graph_obj.mdev)+ continue;+ if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) break;
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org | (970) 217-8978
On 01/28/2016 08:57 AM, Mauro Carvalho Chehab wrote:
Em Wed, 6 Jan 2016 13:27:06 -0700
Shuah Khan [off-list ref] escreveu:
quoted
au0828 is changed to use v4l_enable_media_tuner() to check for
tuner availability from vidioc_g_tuner(), and au0828_v4l2_close(),
before changing tuner settings. If tuner isn't free, return busy
condition from vidioc_g_tuner() and in au0828_v4l2_close() tuner
is left untouched without powering down to save energy.
I am not sure if I did or not. I can double check this case.
Do you have concerns that this won't work?
I guess calling it v4l-enable_media_tuner() is not right, specially
since there are hybrid devices that have DTV (via DVB API) and
S-Video and/or Composite/RCA capture via V4L2 API.
How does v4l-enable_media_source() sound?
thanks,
-- Shuah
@@ -1010,8 +1010,12 @@ static int au0828_v4l2_close(struct file *filp)gotoend;if(dev->users==1){-/* Save some power by putting tuner to sleep */-v4l2_device_call_all(&dev->v4l2_dev,0,core,s_power,0);+/* Save some power by putting tuner to sleep, if it is free */+/* What happens when radio is using tuner?? */+ret=v4l_enable_media_tuner(vdev);+if(ret==0)+v4l2_device_call_all(&dev->v4l2_dev,0,core,+s_power,0);dev->std_set_in_tuner_core=0;/* When close the device, set the usb intf0 into alt0 to free
@@ -1412,10 +1416,16 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audiostaticintvidioc_g_tuner(structfile*file,void*priv,structv4l2_tuner*t){structau0828_dev*dev=video_drvdata(file);+structvideo_device*vfd=video_devdata(file);+intret;if(t->index!=0)return-EINVAL;+ret=v4l_enable_media_tuner(vfd);+if(ret)+returnret;+dprintk(1,"%s called std_set %d dev_state %d\n",__func__,dev->std_set_in_tuner_core,dev->dev_state);
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978
I am not sure if I did or not. I can double check this case.
Do you have concerns that this won't work?
I'm not sure how you expect the MC framework to be handling this case,
but I can tell you that the hardware will *not* support simultaneous
streaming of the DVB feed at the same time as the analog feed, even if
you're using the composite/s-video input and not actually using the
xc5000 tuner in analog mode.
Devin
--
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com
On 01/28/2016 09:36 AM, Mauro Carvalho Chehab wrote:
Em Wed, 6 Jan 2016 13:27:09 -0700
Shuah Khan [off-list ref] escreveu:
quoted
au0828 registers entity_notify hook to create media graph for
the device. This handler runs whenvere a new entity gets added
typo: whenever.
ok
quoted
to the media device. It creates necessary links from video, vbi,
and ALSA entities to decoder and links tuner and decoder entities.
As this handler runs as entities get added, it has to maintain
state on the links it already created. New fields are added to
au0828_dev to keep this state information. entity_notify gets
unregistered before media_device unregister.
Bty, please avoid long paragraphs at the patch description,
and please try to be clearer on your patch descriptions... That
makes boring to read everything. :-;
Yeah I like to add details I consider relevant to the log.
I will try to be concise.
@@ -263,11 +265,16 @@ static int au0828_create_media_graph(struct au0828_dev *dev)structmedia_device*mdev=dev->media_dev;structmedia_entity*entity;structmedia_entity*tuner=NULL,*decoder=NULL;+structmedia_entity*audio_capture=NULL;inti,ret;if(!mdev)return0;+if(dev->tuner_linked&&dev->vdev_linked&&dev->vbi_linked&&+dev->audio_capture_linked)+return0;+media_device_for_each_entity(entity,mdev){switch(entity->function){caseMEDIA_ENT_F_TUNER:
@@ -276,6 +283,9 @@ static int au0828_create_media_graph(struct au0828_dev *dev)caseMEDIA_ENT_F_ATV_DECODER:decoder=entity;break;+caseMEDIA_ENT_F_AUDIO_CAPTURE:+audio_capture=entity;+break;}}
@@ -285,60 +295,77 @@ static int au0828_create_media_graph(struct au0828_dev *dev)if(!decoder)return-EINVAL;-if(tuner){+if(tuner&&!dev->tuner_linked){+dev->tuner=tuner;ret=media_create_pad_link(tuner,TUNER_PAD_IF_OUTPUT,decoder,0,MEDIA_LNK_FL_ENABLED);if(ret)returnret;+dev->tuner_linked=1;}-if(dev->vdev.entity.graph_obj.mdev){+if(dev->vdev.entity.graph_obj.mdev&&!dev->vdev_linked){ret=media_create_pad_link(decoder,AU8522_PAD_VID_OUT,&dev->vdev.entity,0,MEDIA_LNK_FL_ENABLED);if(ret)returnret;+dev->vdev_linked=1;}-if(dev->vbi_dev.entity.graph_obj.mdev){+if(dev->vbi_dev.entity.graph_obj.mdev&&!dev->vbi_linked){ret=media_create_pad_link(decoder,AU8522_PAD_VBI_OUT,&dev->vbi_dev.entity,0,MEDIA_LNK_FL_ENABLED);if(ret)returnret;-}--for(i=0;i<AU0828_MAX_INPUT;i++){-structmedia_entity*ent=&dev->input_ent[i];+dev->vbi_linked=1;-if(!ent->graph_obj.mdev)-continue;+/*+*Inputentitiesareregisteredbeforevbientity,+*creategraphnodesforthemaftervbiiscreated+*/+for(i=0;i<AU0828_MAX_INPUT;i++){+structmedia_entity*ent=&dev->input_ent[i];-if(AUVI_INPUT(i).type==AU0828_VMUX_UNDEFINED)-break;+if(!ent->graph_obj.mdev)+continue;-switch(AUVI_INPUT(i).type){-caseAU0828_VMUX_CABLE:-caseAU0828_VMUX_TELEVISION:-caseAU0828_VMUX_DVB:-if(!tuner)+if(AUVI_INPUT(i).type==AU0828_VMUX_UNDEFINED)break;-ret=media_create_pad_link(ent,0,tuner,-TUNER_PAD_RF_INPUT,-MEDIA_LNK_FL_ENABLED);-if(ret)-returnret;-break;-caseAU0828_VMUX_COMPOSITE:-caseAU0828_VMUX_SVIDEO:-default:/* AU0828_VMUX_DEBUG */-/* FIXME: fix the decoder PAD */-ret=media_create_pad_link(ent,0,decoder,0,0);-if(ret)-returnret;-break;+switch(AUVI_INPUT(i).type){+caseAU0828_VMUX_CABLE:+caseAU0828_VMUX_TELEVISION:+caseAU0828_VMUX_DVB:+if(!tuner)+break;++ret=media_create_pad_link(ent,0,tuner,+TUNER_PAD_RF_INPUT,+MEDIA_LNK_FL_ENABLED);+if(ret)+returnret;+break;+caseAU0828_VMUX_COMPOSITE:+caseAU0828_VMUX_SVIDEO:+default:/* AU0828_VMUX_DEBUG */+/* FIXME: fix the decoder PAD */+ret=media_create_pad_link(ent,0,decoder,+0,0);+if(ret)+returnret;+break;+}}}+if(audio_capture&&!dev->audio_capture_linked){+ret=media_create_pad_link(decoder,AU8522_PAD_AUDIO_OUT,+audio_capture,0,+MEDIA_LNK_FL_ENABLED);+if(ret)+returnret;+dev->audio_capture_linked=1;+}#endifreturn0;}
@@ -349,8 +376,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,#ifdef CONFIG_MEDIA_CONTROLLERintret;-if(dev->media_dev&&-!media_devnode_is_registered(&dev->media_dev->devnode)){+if(!dev->media_dev)+return0;++if(!media_devnode_is_registered(&dev->media_dev->devnode)){/* register media device */ret=media_device_register(dev->media_dev);
Hmm... now I understood why you did the changes on patch 13/31.
I see what you're doing, but not sure if this is a good idea
to have one bool for each possible device. On au0828, the
topology is actually simpler than on other devices, as it
currently supports a very few set of I2C devices, but on other
drivers, things can be messier.
See, for example, two graphs for em28xx-based devices:
https://mchehab.fedorapeople.org/mc-next-gen/wintv_usb2.pnghttps://mchehab.fedorapeople.org/mc-next-gen/hvr_950.png
On the first graph, the tuner is not connected directly to the
analog demod, but, instead, to two other elements:
- tda9887 - for video
- msp3400 - for audio
IMHO, the best way to handle graph setup is that each driver
should handle the links that belong only to them synchronously,
after creating/registering all the entities.
Except for the ALSA part of the graph, we are close
to drivers creating their graphs. You are right that
au0828 graph creation routine shouldn't need to create
links from Alsa mixer to Alsa capture nodes.
So, only the links between two drivers would be asynchronously
created. So, In the case of au0828:
- au0828 core will create the connector entities;
- I2C drivers will create their own entities;
- DVB core will create the DVB entities/interfaces;
- V4L core will create V4L interfaces and I/O entities;
- au0828 V4L driver will create all V4L links, after
ensuring that the needed I2C drivers were bound;
- snd-usb-audio will create all ALSA-specific entities links;
The V4L->ALSA links will either be created by au0828-core,
via the notification handler.
Right - that is part of what au0828_create_media_graph()
is doing now.
With that in mind, I don't see any need to touch at
au0828_create_media_graph(). It will need an extra function
to handle the notification when ALSA gets registered
(or when the entities there are added, whatever works best).
If I understand correctly, what you are saying is:
Don't add async handling that creates V4L->ALSA
to au0828_create_media_graph() and keep that in
an async handler.
I will make changes to address this.
thanks,
-- Shuah
quoted
#endif
};
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org | (970) 217-8978
On 01/28/2016 09:38 AM, Mauro Carvalho Chehab wrote:
Em Wed, 6 Jan 2016 13:27:11 -0700
Shuah Khan [off-list ref] escreveu:
quoted
Create tuner to demod pad link in disabled state to help avoid
disable step when tuner resource is requested by video or audio.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/dvb-core/dvbdev.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
@@ -593,8 +593,9 @@ int dvb_create_media_graph(struct dvb_adapter *adap)}if(tuner&&demod){+/* create tuner to demod link deactivated */ret=media_create_pad_link(tuner,TUNER_PAD_IF_OUTPUT,-demod,0,MEDIA_LNK_FL_ENABLED);+demod,0,0);
This is not right, as it makes no sense for DVB-only drivers.
Right. Not a good change for DVB only drivers. But does make
sense on hybrid. I will make sure it gets done only in hyrbid
cases.
thanks,
-- Shuah
quoted
if (ret)
return ret;
}
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978
On 01/28/2016 09:43 AM, Mauro Carvalho Chehab wrote:
Em Wed, 6 Jan 2016 13:27:12 -0700
Shuah Khan [off-list ref] escreveu:
quoted
Implements enable_source and disable_source handlers for other
drivers (v4l2-core, dvb-core, and ALSA) to use to check for
tuner connected to the decoder and activate the link if tuner
is free, and deactivate and free the tuner when it is no longer
needed.
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-core.c | 148 +++++++++++++++++++++++++++++++++
drivers/media/usb/au0828/au0828.h | 2 +
2 files changed, 150 insertions(+)
@@ -370,6 +370,150 @@ static int au0828_create_media_graph(struct au0828_dev *dev)return0;}+staticintau0828_enable_source(structmedia_entity*entity,+structmedia_pipeline*pipe)+{
The best would be to put those enable source stuff at the core, in a way
that other drivers could share it.
Hans and I discussed this at the Media Summit in Finland.
It will be very difficult to make this work in a generic
way. Besides, bridge driver knows the hardware it has and
it would make sense for it to implement enable and disable
source handlers.
Not sure about the implementation, as this requires testing ;)
Did you consider the cases where the source connector is S-Video
or Composite?
I think you asked this question on another patch and Devin
responded to that thread. Let's discuss it there.
thanks,
-- Shuah
quoted
+#ifdef CONFIG_MEDIA_CONTROLLER+ struct media_entity *source;+ struct media_entity *sink;+ struct media_link *link, *found_link = NULL;+ int ret = 0;+ struct media_device *mdev = entity->graph_obj.mdev;+ struct au0828_dev *dev;++ if (!mdev)+ return -ENODEV;++ /* for Audio and Video entities, source is the decoder */+ mutex_lock(&mdev->graph_mutex);++ dev = mdev->source_priv;+ if (!dev->tuner || !dev->decoder) {+ ret = -ENODEV;+ goto end;+ }++ /*+ * For Audio and V4L2 entity, find the link to which decoder+ * is the sink. Look for an active link between decoder and+ * tuner, if one exists, nothing to do. If not, look for any+ * active links between tuner and any other entity. If one+ * exists, tuner is busy. If tuner is free, setup link and+ * start pipeline from source (tuner).+ * For DVB FE entity, the source for the link is the tuner.+ * Check if tuner is available and setup link and start+ * pipeline.+ */+ if (entity->function != MEDIA_ENT_F_DTV_DEMOD)+ sink = dev->decoder;+ else+ sink = entity;++ /* Is an active link between sink and tuner */+ if (dev->active_link) {+ if (dev->active_link->sink->entity == sink &&+ dev->active_link->source->entity == dev->tuner) {+ ret = 0;+ goto end;+ } else {+ ret = -EBUSY;+ goto end;+ }+ }++ list_for_each_entry(link, &sink->links, list) {+ /* Check sink, and source */+ if (link->sink->entity == sink &&+ link->source->entity == dev->tuner) {+ found_link = link;+ break;+ }+ }++ if (!found_link) {+ ret = -ENODEV;+ goto end;+ }++ /* activate link between source and sink and start pipeline */+ source = found_link->source->entity;+ ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);+ if (ret) {+ pr_err(+ "Activate tuner link %s->%s. Error %d\n",+ source->name, sink->name, ret);+ goto end;+ }++ ret = __media_entity_pipeline_start(entity, pipe);+ if (ret) {+ pr_err("Start Pipeline: %s->%s Error %d\n",+ source->name, entity->name, ret);+ ret = __media_entity_setup_link(found_link, 0);+ pr_err("Deactive link Error %d\n", ret);+ goto end;+ }+ /*+ * save active link and active link owner to avoid audio+ * deactivating video owned link from disable_source and+ * vice versa+ */+ dev->active_link = found_link;+ dev->active_link_owner = entity;+end:+ mutex_unlock(&mdev->graph_mutex);+ pr_debug("au0828_enable_source() end %s %d %d\n",+ entity->name, entity->function, ret);+ return ret;+#endif+ return 0;+}++static void au0828_disable_source(struct media_entity *entity)+{+#ifdef CONFIG_MEDIA_CONTROLLER+ struct media_entity *sink;+ int ret = 0;+ struct media_device *mdev = entity->graph_obj.mdev;+ struct au0828_dev *dev;++ if (!mdev)+ return;++ mutex_lock(&mdev->graph_mutex);+ dev = mdev->source_priv;+ if (!dev->tuner || !dev->decoder || !dev->active_link) {+ ret = -ENODEV;+ goto end;+ }++ if (entity->function != MEDIA_ENT_F_DTV_DEMOD)+ sink = dev->decoder;+ else+ sink = entity;++ /* link is active - stop pipeline from source (tuner) */+ if (dev->active_link && dev->active_link->sink->entity == sink &&+ dev->active_link->source->entity == dev->tuner) {+ /*+ * prevent video from deactivating link when audio+ * has active pipeline+ */+ if (dev->active_link_owner != entity)+ goto end;+ __media_entity_pipeline_stop(entity);+ ret = __media_entity_setup_link(dev->active_link, 0);+ if (ret)+ pr_err("Deactive link Error %d\n", ret);+ dev->active_link = NULL;+ dev->active_link_owner = NULL;+ }++end:+ mutex_unlock(&mdev->graph_mutex);+#endif+}+ static int au0828_media_device_register(struct au0828_dev *dev, struct usb_device *udev) {
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978
On 01/28/2016 09:44 AM, Mauro Carvalho Chehab wrote:
Em Wed, 6 Jan 2016 13:27:13 -0700
Shuah Khan [off-list ref] escreveu:
quoted
Add a new wrapper function to au0828_create_media_graph()
to be called as an entity_notify function to fix null
pointer dereference. A rebasing mistake resulted in
registering au0828_create_media_graph() without the
correct parameters which lead to the following
null pointer dereference:
[ 69.006164] Call Trace:
[ 69.006169] [<ffffffff81a9a1b0>] dump_stack+0x44/0x64
[ 69.006175] [<ffffffff81503af9>] print_trailer+0xf9/0x150
[ 69.006180] [<ffffffff81509284>] object_err+0x34/0x40
[ 69.006185] [<ffffffff815063c4>] ? ___slab_alloc+0x4c4/0x4e0
[ 69.006190] [<ffffffff8150b732>] kasan_report_error+0x212/0x520
[ 69.006196] [<ffffffff815063c4>] ? ___slab_alloc+0x4c4/0x4e0
[ 69.006201] [<ffffffff8150ba83>] __asan_report_load1_noabort+0x43/0x50
[ 69.006208] [<ffffffffa0d30991>] ? au0828_create_media_graph+0x641/0x730 [au0828]
[ 69.006215] [<ffffffffa0d30991>] au0828_create_media_graph+0x641/0x730 [au0828]
[ 69.006221] [<ffffffff82245c3d>] media_device_register_entity+0x33d/0x4f0
[ 69.006234] [<ffffffffa0ebeb1c>] media_stream_init+0x2ac/0x610 [snd_usb_audio]
[ 69.006247] [<ffffffffa0ea9a70>] snd_usb_pcm_open+0xcd0/0x1280 [snd_usb_audio]
Please merge the fix with the patch that caused the regression.
@@ -370,6 +370,20 @@ static int au0828_create_media_graph(struct au0828_dev *dev)return0;}+voidau0828_create_media_graph_notify(structmedia_entity*new,+void*notify_data)+{+#ifdef CONFIG_MEDIA_CONTROLLER+structau0828_dev*dev=(structau0828_dev*)notify_data;+intret;++ret=au0828_create_media_graph(dev);+if(ret)+pr_err("%s() media graph create failed for new entity %s\n",+__func__,new->name);+#endif+}+staticintau0828_enable_source(structmedia_entity*entity,structmedia_pipeline*pipe){
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978
On 01/28/2016 09:45 AM, Mauro Carvalho Chehab wrote:
Em Wed, 6 Jan 2016 14:01:54 -0700
Shuah Khan [off-list ref] escreveu:
quoted
entity_notify handlers are removed from media_device_unregister().
There is no need to call media_device_unregister_entity_notify()
to do that right before calling media_device_unregister().
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org | (970) 217-8978
On 01/28/2016 09:58 AM, Mauro Carvalho Chehab wrote:
Em Wed, 6 Jan 2016 13:27:17 -0700
Shuah Khan [off-list ref] escreveu:
quoted
Change au0828_create_media_graph() to create pad link
between MEDIA_ENT_F_AUDIO_MIXER entity and decoder's
AU8522_PAD_AUDIO_OUT. With mixer entity now linked to
decoder, change to link MEDIA_ENT_F_AUDIO_CAPTURE to
mixer's source pad.
See my comments about doing only this asynchronously on the previous
patches.
Yes. I responded to that one. I might collapse both ALSA
patch that adds capture and mixer into one. Might make
it lot easier and handle them at the same time.
thanks,
-- Shuah
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978
Em Thu, 28 Jan 2016 13:05:35 -0700
Shuah Khan [off-list ref] escreveu:
On 01/28/2016 09:36 AM, Mauro Carvalho Chehab wrote:
quoted
Em Wed, 6 Jan 2016 13:27:09 -0700
Shuah Khan [off-list ref] escreveu:
quoted
au0828 registers entity_notify hook to create media graph for
the device. This handler runs whenvere a new entity gets added
typo: whenever.
ok
quoted
quoted
to the media device. It creates necessary links from video, vbi,
and ALSA entities to decoder and links tuner and decoder entities.
As this handler runs as entities get added, it has to maintain
state on the links it already created. New fields are added to
au0828_dev to keep this state information. entity_notify gets
unregistered before media_device unregister.
Bty, please avoid long paragraphs at the patch description,
and please try to be clearer on your patch descriptions... That
makes boring to read everything. :-;
Yeah I like to add details I consider relevant to the log.
I will try to be concise.
It is not a matter of removing details, but better organizing the
ideas. A single huge paragraph with lots of contents mixed inside
doesn't make easier for the readers ;)
@@ -263,11 +265,16 @@ static int au0828_create_media_graph(struct au0828_dev *dev)structmedia_device*mdev=dev->media_dev;structmedia_entity*entity;structmedia_entity*tuner=NULL,*decoder=NULL;+structmedia_entity*audio_capture=NULL;inti,ret;if(!mdev)return0;+if(dev->tuner_linked&&dev->vdev_linked&&dev->vbi_linked&&+dev->audio_capture_linked)+return0;+media_device_for_each_entity(entity,mdev){switch(entity->function){caseMEDIA_ENT_F_TUNER:
@@ -276,6 +283,9 @@ static int au0828_create_media_graph(struct au0828_dev *dev)caseMEDIA_ENT_F_ATV_DECODER:decoder=entity;break;+caseMEDIA_ENT_F_AUDIO_CAPTURE:+audio_capture=entity;+break;}}
@@ -285,60 +295,77 @@ static int au0828_create_media_graph(struct au0828_dev *dev)if(!decoder)return-EINVAL;-if(tuner){+if(tuner&&!dev->tuner_linked){+dev->tuner=tuner;ret=media_create_pad_link(tuner,TUNER_PAD_IF_OUTPUT,decoder,0,MEDIA_LNK_FL_ENABLED);if(ret)returnret;+dev->tuner_linked=1;}-if(dev->vdev.entity.graph_obj.mdev){+if(dev->vdev.entity.graph_obj.mdev&&!dev->vdev_linked){ret=media_create_pad_link(decoder,AU8522_PAD_VID_OUT,&dev->vdev.entity,0,MEDIA_LNK_FL_ENABLED);if(ret)returnret;+dev->vdev_linked=1;}-if(dev->vbi_dev.entity.graph_obj.mdev){+if(dev->vbi_dev.entity.graph_obj.mdev&&!dev->vbi_linked){ret=media_create_pad_link(decoder,AU8522_PAD_VBI_OUT,&dev->vbi_dev.entity,0,MEDIA_LNK_FL_ENABLED);if(ret)returnret;-}--for(i=0;i<AU0828_MAX_INPUT;i++){-structmedia_entity*ent=&dev->input_ent[i];+dev->vbi_linked=1;-if(!ent->graph_obj.mdev)-continue;+/*+*Inputentitiesareregisteredbeforevbientity,+*creategraphnodesforthemaftervbiiscreated+*/+for(i=0;i<AU0828_MAX_INPUT;i++){+structmedia_entity*ent=&dev->input_ent[i];-if(AUVI_INPUT(i).type==AU0828_VMUX_UNDEFINED)-break;+if(!ent->graph_obj.mdev)+continue;-switch(AUVI_INPUT(i).type){-caseAU0828_VMUX_CABLE:-caseAU0828_VMUX_TELEVISION:-caseAU0828_VMUX_DVB:-if(!tuner)+if(AUVI_INPUT(i).type==AU0828_VMUX_UNDEFINED)break;-ret=media_create_pad_link(ent,0,tuner,-TUNER_PAD_RF_INPUT,-MEDIA_LNK_FL_ENABLED);-if(ret)-returnret;-break;-caseAU0828_VMUX_COMPOSITE:-caseAU0828_VMUX_SVIDEO:-default:/* AU0828_VMUX_DEBUG */-/* FIXME: fix the decoder PAD */-ret=media_create_pad_link(ent,0,decoder,0,0);-if(ret)-returnret;-break;+switch(AUVI_INPUT(i).type){+caseAU0828_VMUX_CABLE:+caseAU0828_VMUX_TELEVISION:+caseAU0828_VMUX_DVB:+if(!tuner)+break;++ret=media_create_pad_link(ent,0,tuner,+TUNER_PAD_RF_INPUT,+MEDIA_LNK_FL_ENABLED);+if(ret)+returnret;+break;+caseAU0828_VMUX_COMPOSITE:+caseAU0828_VMUX_SVIDEO:+default:/* AU0828_VMUX_DEBUG */+/* FIXME: fix the decoder PAD */+ret=media_create_pad_link(ent,0,decoder,+0,0);+if(ret)+returnret;+break;+}}}+if(audio_capture&&!dev->audio_capture_linked){+ret=media_create_pad_link(decoder,AU8522_PAD_AUDIO_OUT,+audio_capture,0,+MEDIA_LNK_FL_ENABLED);+if(ret)+returnret;+dev->audio_capture_linked=1;+}#endifreturn0;}
@@ -349,8 +376,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,#ifdef CONFIG_MEDIA_CONTROLLERintret;-if(dev->media_dev&&-!media_devnode_is_registered(&dev->media_dev->devnode)){+if(!dev->media_dev)+return0;++if(!media_devnode_is_registered(&dev->media_dev->devnode)){/* register media device */ret=media_device_register(dev->media_dev);
Hmm... now I understood why you did the changes on patch 13/31.
I see what you're doing, but not sure if this is a good idea
to have one bool for each possible device. On au0828, the
topology is actually simpler than on other devices, as it
currently supports a very few set of I2C devices, but on other
drivers, things can be messier.
See, for example, two graphs for em28xx-based devices:
https://mchehab.fedorapeople.org/mc-next-gen/wintv_usb2.pnghttps://mchehab.fedorapeople.org/mc-next-gen/hvr_950.png
On the first graph, the tuner is not connected directly to the
analog demod, but, instead, to two other elements:
- tda9887 - for video
- msp3400 - for audio
IMHO, the best way to handle graph setup is that each driver
should handle the links that belong only to them synchronously,
after creating/registering all the entities.
Except for the ALSA part of the graph, we are close
to drivers creating their graphs. You are right that
au0828 graph creation routine shouldn't need to create
links from Alsa mixer to Alsa capture nodes.
quoted
So, only the links between two drivers would be asynchronously
created. So, In the case of au0828:
- au0828 core will create the connector entities;
- I2C drivers will create their own entities;
- DVB core will create the DVB entities/interfaces;
- V4L core will create V4L interfaces and I/O entities;
- au0828 V4L driver will create all V4L links, after
ensuring that the needed I2C drivers were bound;
- snd-usb-audio will create all ALSA-specific entities links;
The V4L->ALSA links will either be created by au0828-core,
via the notification handler.
Right - that is part of what au0828_create_media_graph()
is doing now.
quoted
With that in mind, I don't see any need to touch at
au0828_create_media_graph(). It will need an extra function
to handle the notification when ALSA gets registered
(or when the entities there are added, whatever works best).
If I understand correctly, what you are saying is:
Don't add async handling that creates V4L->ALSA
to au0828_create_media_graph() and keep that in
an async handler.
I will make changes to address this.
Yes, instead of modifying the existing routine to make it async
and harder to read, add a separate function that will handle
just the things that need to be async there. That should reduce
the code complexity and the possibility of having potencial
hidden race conditions.
It also allows more complex logic on the sync routine when
it is needed, like the one needed to identify if the tuner is alone,
or if it has multiple IF and/or video processors (with is common
on some kinds of hardware). See such logic at:
https://git.linuxtv.org/mchehab/experimental.git/commit/?h=mc_em28xx&id=f6c245842bc4ec6faf66aaf8b85baad47a730e3b
on em28xx_v4l2_create_media_graph() where the tuner logic
needs to check for both audio and video IF-PLL hardware.
Regards,
Mauro
On 01/28/2016 10:05 AM, Mauro Carvalho Chehab wrote:
Em Wed, 6 Jan 2016 13:27:20 -0700
Shuah Khan [off-list ref] escreveu:
quoted
Change au0828_unregister_media_device() to check media
device media device unregister is in progress and avoid
calling media_device_unregister() and other cleanup done
in au0828_unregister_media_device().
Signed-off-by: Shuah Khan <redacted>
---
drivers/media/usb/au0828/au0828-core.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
Hope you saw my response to[PATCH 29/31] on why ensuring
two drivers don't get into unregister is necessary.
Could you please elaborate on kref. Are you saying adding
kref to struct media_device?
thanks,
-- Shuah
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org | (970) 217-8978
On 01/28/2016 10:15 AM, Mauro Carvalho Chehab wrote:
Em Thu, 28 Jan 2016 09:28:37 -0700
Shuah Khan [off-list ref] escreveu:
quoted
On 01/28/2016 08:19 AM, Mauro Carvalho Chehab wrote:
quoted
Em Wed, 6 Jan 2016 13:26:53 -0700
Shuah Khan [off-list ref] escreveu:
quoted
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 need to run these handlers. The enable_source handler
finds source entity for the passed in entity and check if it is
available, and activate the link using __media_entity_setup_link()
interface. Bridge driver is expected to implement and set these
handlers and private data when media_device is registered or when
bridge driver finds the media_device during probe. This is to enable
the use-case to find tuner entity connected to the decoder entity and
check if it is available, and activate it and start pipeline between
the source and the entity. The disable_source handler deactivates the
link and stops the pipeline. This handler can be invoked from the
media core (v4l-core, dvb-core) as well as other drivers such as ALSA
that control the media device.
Signed-off-by: Shuah Khan <redacted>
---
include/media/media-device.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
@@ -333,6 +333,25 @@ struct media_device {/* Serializes graph operations. */structmutexgraph_mutex;+/* Handlers to find source entity for the sink entity and+*checkifitisavailable,andactivatethelinkusing+*media_entity_setup_link()interfaceandstartpipeline+*fromthesourcetotheentity.+*Bridgedriverisexpectedtoimplementandsetthe+*handlerwhenmedia_deviceisregisteredorwhen+*bridgedriverfindsthemedia_deviceduringprobe.+*Bridgedriversetssource_privwithinformation+*necessarytorunenable/disablesourcehandlers.+*+*Use-case:findtunerentityconnectedtothedecoder+*entityandcheckifitisavailable,andactivatethe+*usingmedia_entity_setup_link()ifitisavailable.+*/+void*source_priv;+int(*enable_source)(structmedia_entity*entity,+structmedia_pipeline*pipe);+void(*disable_source)(structmedia_entity*entity);
Please document the new fields at the right place (Kernel-doc
comment declared before the struct).
Is this used by the media core? If so, please but the implementation
here, to make it clearer why we need those things.
quoted
+ int (*link_notify)(struct media_link *link, u32 flags, unsigned int notification); };
Hi Mauro,
I don't have any problems adding documentation. I would
like to add documentation in a add-on to the patch series.
The main reason is once I add documentation to this patch,
the rest of the patches on this file don't apply and require
rebase and rework. I went though a couple of rounds of this
while you were adding documentation to the interfaces you
added.
How about I add the documentation patches at the end of
the patch series? I am concerned that rebasing for the
documentation changes will introduce bugs. Are you okay
with this proposal?
I'm ok with that for those inlined kernel-doc stuff. On
the changes at the uapi/linux/media.h, I would prefer if
you could add the documentation together with the patch,
as it makes clearer for the reviewers. As you only
touched it on one or two patches, this won't cause any
breakages on the remaining patches.
ok I can add documentation to uapi/linux/media.h in the
same patch that adds new defines.
thanks,
-- Shuah
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978
On 01/28/2016 10:28 AM, Mauro Carvalho Chehab wrote:
Em Thu, 28 Jan 2016 10:04:24 -0700
Shuah Khan [off-list ref] escreveu:
quoted
On 01/28/2016 10:01 AM, Mauro Carvalho Chehab wrote:
quoted
Em Wed, 6 Jan 2016 13:27:18 -0700
Shuah Khan [off-list ref] escreveu:
quoted
Add support to track media device unregister in progress
state to prevent more than one driver entering unregister.
This enables fixing the general protection faults while
snd-usb-audio was cleaning up media resources for pcm
streams and mixers. In this patch a new interface is added
to return the unregister in progress state. Subsequent
patches to snd-usb-audio and au0828-core use this interface
to avoid entering unregister and attempting to unregister
entities and remove devnodes while unregister is in progress.
Media device unregister removes entities and interface nodes.
Hmm... isn't the spinlock enough to serialize it? It seems weird the
need of an extra bool here to warrant that this is really serialized.
The spinlock and check for media_devnode_is_registered(&mdev->devnode)
aren't enough to ensure only one driver enters the unregister.
Please
note that the devnode isn't marked unregistered until the end in
media_device_unregister().
I guess the call to:
device_remove_file(&mdev->devnode.dev, &dev_attr_model);
IMO, This should be, instead, at media_devnode_unregister().
Then, we can change the logic at media_devnode_unregister() to:
void media_devnode_unregister(struct media_devnode *mdev)
{
mutex_lock(&media_devnode_lock);
/* Check if mdev was ever registered at all */
if (!media_devnode_is_registered(mdev)) {
mutex_unlock(&media_devnode_lock);
return;
}
clear_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
mutex_unlock(&media_devnode_lock);
device_remove_file(&mdev->devnode.dev, &dev_attr_model);
device_unregister(&mdev->dev);
}
This sounds enough to avoid device_unregister() or device_remove_file()
to be called twice.
I can give it a try. There might other problems that could
result from media device being a devres in this case. The
last put_device on the usbdev parent device (media device
is created as devres for this), all device resources get
released. That might have to be solved in a different way.
For now I will see if your solution works.
thanks,
-- Shuah
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978