Commit 4417967b authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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 driver-core-next

Daniel writes:

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.

* tag 'topic/component-typed-2019-02-11' of git://anongit.freedesktop.org/drm/drm-intel:
  i915/snd_hdac: I915 subcomponent for the snd_hdac
  components: multiple components for a device
  component: Add documentation
parents 9481caf3 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 generic_pm_domain| replace:: :c:type:`struct generic_pm_domain <generic_pm_domain>`
.. _device_link:
============
Device links
============
......
......@@ -22,6 +22,7 @@ available subsections can be seen below.
device_connection
dma-buf
device_link
component
message-based
sound
frame-buffer
......
This diff is collapsed.
......@@ -984,7 +984,9 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv)
{
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) {
DRM_ERROR("failed to add audio component (%d)\n", ret);
/* continue with reduced functionality */
......
......@@ -26,6 +26,10 @@
#include "drm_audio_component.h"
enum i915_component_type {
I915_COMPONENT_AUDIO = 1,
};
/* MAX_PORT is the number of port
* It must be sync with I915_MAX_PORTS defined i915_drv.h
*/
......
......@@ -4,16 +4,38 @@
#include <linux/stddef.h>
struct device;
/**
* struct component_ops - callbacks for component drivers
*
* Components are registered with component_add() and unregistered with
* component_del().
*/
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,
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 *master_data);
};
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 *);
int component_bind_all(struct device *master, void *master_data);
......@@ -21,8 +43,42 @@ void component_unbind_all(struct device *master, void *master_data);
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 {
/**
* @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);
/**
* @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);
};
......@@ -37,7 +93,27 @@ void component_match_add_release(struct device *master,
struct component_match **matchptr,
void (*release)(struct device *, void *),
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,
struct component_match **matchptr,
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,
bool *audio_enabled, char *buffer, int max_bytes);
int snd_hdac_acomp_init(struct hdac_bus *bus,
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);
int snd_hdac_acomp_exit(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
}
static inline int snd_hdac_acomp_init(struct hdac_bus *bus,
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)
{
return -ENODEV;
......
......@@ -269,7 +269,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier);
*/
int snd_hdac_acomp_init(struct hdac_bus *bus,
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)
{
struct component_match *match = NULL;
......@@ -288,7 +288,7 @@ int snd_hdac_acomp_init(struct hdac_bus *bus,
bus->audio_component = 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,
match);
if (ret < 0)
......
......@@ -82,9 +82,11 @@ void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
}
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 */
......
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