Commit e179d8e0 authored by Maxime Ripard's avatar Maxime Ripard

Merge tag 'topic/component-typed-2019-02-11' of...

Merge tag 'topic/component-typed-2019-02-11' of git://anongit.freedesktop.org/drm/drm-intel into drm-misc-next

typed componented support + i915/snd-hda changes

This is needed by the new MEI-HDCP support in i915, so will need to go
in through drm and drivers-misc trees at least.
Signed-off-by: default avatarMaxime Ripard <maxime.ripard@bootlin.com>

# gpg: Signature made Mon 11 Feb 2019 06:06:26 PM CET
# gpg:                using RSA key 6F89C6EA32EEF18E5723E3DF4C0F727BF098AA71
# gpg: Can't check signature: No public key
From: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/CAKMK7uHU37VLbe4RBZ3GOow+=pupYAHotkVrpqJeiUcpSfjX8Q@mail.gmail.com
parents ae6ba10d 8857c7d0
======================================
Component Helper for Aggregate Drivers
======================================
.. kernel-doc:: drivers/base/component.c
:doc: overview
API
===
.. kernel-doc:: include/linux/component.h
:internal:
.. kernel-doc:: drivers/base/component.c
:export:
.. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>` .. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>`
.. |struct generic_pm_domain| replace:: :c:type:`struct generic_pm_domain <generic_pm_domain>` .. |struct generic_pm_domain| replace:: :c:type:`struct generic_pm_domain <generic_pm_domain>`
.. _device_link:
============ ============
Device links Device links
============ ============
......
...@@ -22,6 +22,7 @@ available subsections can be seen below. ...@@ -22,6 +22,7 @@ available subsections can be seen below.
device_connection device_connection
dma-buf dma-buf
device_link device_link
component
message-based message-based
sound sound
frame-buffer frame-buffer
......
This diff is collapsed.
...@@ -984,7 +984,9 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv) ...@@ -984,7 +984,9 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv)
{ {
int ret; int ret;
ret = component_add(dev_priv->drm.dev, &i915_audio_component_bind_ops); ret = component_add_typed(dev_priv->drm.dev,
&i915_audio_component_bind_ops,
I915_COMPONENT_AUDIO);
if (ret < 0) { if (ret < 0) {
DRM_ERROR("failed to add audio component (%d)\n", ret); DRM_ERROR("failed to add audio component (%d)\n", ret);
/* continue with reduced functionality */ /* continue with reduced functionality */
......
...@@ -26,6 +26,10 @@ ...@@ -26,6 +26,10 @@
#include "drm_audio_component.h" #include "drm_audio_component.h"
enum i915_component_type {
I915_COMPONENT_AUDIO = 1,
};
/* MAX_PORT is the number of port /* MAX_PORT is the number of port
* It must be sync with I915_MAX_PORTS defined i915_drv.h * It must be sync with I915_MAX_PORTS defined i915_drv.h
*/ */
......
...@@ -4,16 +4,38 @@ ...@@ -4,16 +4,38 @@
#include <linux/stddef.h> #include <linux/stddef.h>
struct device; struct device;
/**
* struct component_ops - callbacks for component drivers
*
* Components are registered with component_add() and unregistered with
* component_del().
*/
struct component_ops { struct component_ops {
/**
* @bind:
*
* Called through component_bind_all() when the aggregate driver is
* ready to bind the overall driver.
*/
int (*bind)(struct device *comp, struct device *master, int (*bind)(struct device *comp, struct device *master,
void *master_data); void *master_data);
/**
* @unbind:
*
* Called through component_unbind_all() when the aggregate driver is
* ready to bind the overall driver, or when component_bind_all() fails
* part-ways through and needs to unbind some already bound components.
*/
void (*unbind)(struct device *comp, struct device *master, void (*unbind)(struct device *comp, struct device *master,
void *master_data); void *master_data);
}; };
int component_add(struct device *, const struct component_ops *); int component_add(struct device *, const struct component_ops *);
int component_add_typed(struct device *dev, const struct component_ops *ops,
int subcomponent);
void component_del(struct device *, const struct component_ops *); void component_del(struct device *, const struct component_ops *);
int component_bind_all(struct device *master, void *master_data); int component_bind_all(struct device *master, void *master_data);
...@@ -21,8 +43,42 @@ void component_unbind_all(struct device *master, void *master_data); ...@@ -21,8 +43,42 @@ void component_unbind_all(struct device *master, void *master_data);
struct master; struct master;
/**
* struct component_master_ops - callback for the aggregate driver
*
* Aggregate drivers are registered with component_master_add_with_match() and
* unregistered with component_master_del().
*/
struct component_master_ops { struct component_master_ops {
/**
* @bind:
*
* Called when all components or the aggregate driver, as specified in
* the match list passed to component_master_add_with_match(), are
* ready. Usually there are 3 steps to bind an aggregate driver:
*
* 1. Allocate a structure for the aggregate driver.
*
* 2. Bind all components to the aggregate driver by calling
* component_bind_all() with the aggregate driver structure as opaque
* pointer data.
*
* 3. Register the aggregate driver with the subsystem to publish its
* interfaces.
*
* Note that the lifetime of the aggregate driver does not align with
* any of the underlying &struct device instances. Therefore devm cannot
* be used and all resources acquired or allocated in this callback must
* be explicitly released in the @unbind callback.
*/
int (*bind)(struct device *master); int (*bind)(struct device *master);
/**
* @unbind:
*
* Called when either the aggregate driver, using
* component_master_del(), or one of its components, using
* component_del(), is unregistered.
*/
void (*unbind)(struct device *master); void (*unbind)(struct device *master);
}; };
...@@ -37,7 +93,27 @@ void component_match_add_release(struct device *master, ...@@ -37,7 +93,27 @@ void component_match_add_release(struct device *master,
struct component_match **matchptr, struct component_match **matchptr,
void (*release)(struct device *, void *), void (*release)(struct device *, void *),
int (*compare)(struct device *, void *), void *compare_data); int (*compare)(struct device *, void *), void *compare_data);
void component_match_add_typed(struct device *master,
struct component_match **matchptr,
int (*compare_typed)(struct device *, int, void *), void *compare_data);
/**
* component_match_add - add a compent match
* @master: device with the aggregate driver
* @matchptr: pointer to the list of component matches
* @compare: compare function to match against all components
* @compare_data: opaque pointer passed to the @compare function
*
* Adds a new component match to the list stored in @matchptr, which the @master
* aggregate driver needs to function. The list of component matches pointed to
* by @matchptr must be initialized to NULL before adding the first match. This
* only matches against components added with component_add().
*
* The allocated match list in @matchptr is automatically released using devm
* actions.
*
* See also component_match_add_release() and component_match_add_typed().
*/
static inline void component_match_add(struct device *master, static inline void component_match_add(struct device *master,
struct component_match **matchptr, struct component_match **matchptr,
int (*compare)(struct device *, void *), void *compare_data) int (*compare)(struct device *, void *), void *compare_data)
......
...@@ -20,7 +20,7 @@ int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, ...@@ -20,7 +20,7 @@ int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
bool *audio_enabled, char *buffer, int max_bytes); bool *audio_enabled, char *buffer, int max_bytes);
int snd_hdac_acomp_init(struct hdac_bus *bus, int snd_hdac_acomp_init(struct hdac_bus *bus,
const struct drm_audio_component_audio_ops *aops, const struct drm_audio_component_audio_ops *aops,
int (*match_master)(struct device *, void *), int (*match_master)(struct device *, int, void *),
size_t extra_size); size_t extra_size);
int snd_hdac_acomp_exit(struct hdac_bus *bus); int snd_hdac_acomp_exit(struct hdac_bus *bus);
int snd_hdac_acomp_register_notifier(struct hdac_bus *bus, int snd_hdac_acomp_register_notifier(struct hdac_bus *bus,
...@@ -47,7 +47,8 @@ static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t ni ...@@ -47,7 +47,8 @@ static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t ni
} }
static inline int snd_hdac_acomp_init(struct hdac_bus *bus, static inline int snd_hdac_acomp_init(struct hdac_bus *bus,
const struct drm_audio_component_audio_ops *aops, const struct drm_audio_component_audio_ops *aops,
int (*match_master)(struct device *, void *), int (*match_master)(struct device *,
int, void *),
size_t extra_size) size_t extra_size)
{ {
return -ENODEV; return -ENODEV;
......
...@@ -269,7 +269,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier); ...@@ -269,7 +269,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier);
*/ */
int snd_hdac_acomp_init(struct hdac_bus *bus, int snd_hdac_acomp_init(struct hdac_bus *bus,
const struct drm_audio_component_audio_ops *aops, const struct drm_audio_component_audio_ops *aops,
int (*match_master)(struct device *, void *), int (*match_master)(struct device *, int, void *),
size_t extra_size) size_t extra_size)
{ {
struct component_match *match = NULL; struct component_match *match = NULL;
...@@ -288,7 +288,7 @@ int snd_hdac_acomp_init(struct hdac_bus *bus, ...@@ -288,7 +288,7 @@ int snd_hdac_acomp_init(struct hdac_bus *bus,
bus->audio_component = acomp; bus->audio_component = acomp;
devres_add(dev, acomp); devres_add(dev, acomp);
component_match_add(dev, &match, match_master, bus); component_match_add_typed(dev, &match, match_master, bus);
ret = component_master_add_with_match(dev, &hdac_component_master_ops, ret = component_master_add_with_match(dev, &hdac_component_master_ops,
match); match);
if (ret < 0) if (ret < 0)
......
...@@ -82,9 +82,11 @@ void snd_hdac_i915_set_bclk(struct hdac_bus *bus) ...@@ -82,9 +82,11 @@ void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
} }
EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk); EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk);
static int i915_component_master_match(struct device *dev, void *data) static int i915_component_master_match(struct device *dev, int subcomponent,
void *data)
{ {
return !strcmp(dev->driver->name, "i915"); return !strcmp(dev->driver->name, "i915") &&
subcomponent == I915_COMPONENT_AUDIO;
} }
/* check whether intel graphics is present */ /* check whether intel graphics is present */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment