Commit b08e776c authored by Joonas Lahtinen's avatar Joonas Lahtinen

Merge tag 'topic/mei-hdcp-2019-02-19' of...

Merge tag 'topic/mei-hdcp-2019-02-19' of git://anongit.freedesktop.org/drm/drm-intel into drm-intel-next-queued

Prep patches + headers for the mei-hdcp/i915 component interfaces

Also contains the prep work in the component helpers plus adjustements
for the snd-hda/i915 component interface.

Plus one small static inline in the drm_hdcp.h header that both i915
and mei_hdcp will need.
Signed-off-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
From: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20190219071619.GA11016@phenom.ffwll.local
parents d0781a89 35c02725
======================================
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.
...@@ -989,7 +989,9 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv) ...@@ -989,7 +989,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,7 @@ ...@@ -26,6 +26,7 @@
#define _INTEL_DISPLAY_H_ #define _INTEL_DISPLAY_H_
#include <drm/drm_util.h> #include <drm/drm_util.h>
#include <drm/i915_drm.h>
enum i915_gpio { enum i915_gpio {
GPIOA, GPIOA,
...@@ -150,21 +151,6 @@ enum plane_id { ...@@ -150,21 +151,6 @@ enum plane_id {
for ((__p) = PLANE_PRIMARY; (__p) < I915_MAX_PLANES; (__p)++) \ for ((__p) = PLANE_PRIMARY; (__p) < I915_MAX_PLANES; (__p)++) \
for_each_if((__crtc)->plane_ids_mask & BIT(__p)) for_each_if((__crtc)->plane_ids_mask & BIT(__p))
enum port {
PORT_NONE = -1,
PORT_A = 0,
PORT_B,
PORT_C,
PORT_D,
PORT_E,
PORT_F,
I915_MAX_PORTS
};
#define port_name(p) ((p) + 'A')
/* /*
* Ports identifier referenced from other drivers. * Ports identifier referenced from other drivers.
* Expected to remain stable over time * Expected to remain stable over time
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#define _DRM_AUDIO_COMPONENT_H_ #define _DRM_AUDIO_COMPONENT_H_
struct drm_audio_component; struct drm_audio_component;
struct device;
/** /**
* struct drm_audio_component_ops - Ops implemented by DRM driver, called by hda driver * struct drm_audio_component_ops - Ops implemented by DRM driver, called by hda driver
......
...@@ -252,4 +252,22 @@ struct hdcp2_dp_errata_stream_type { ...@@ -252,4 +252,22 @@ struct hdcp2_dp_errata_stream_type {
#define HDCP_2_2_HDMI_RXSTATUS_READY(x) ((x) & BIT(2)) #define HDCP_2_2_HDMI_RXSTATUS_READY(x) ((x) & BIT(2))
#define HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(x) ((x) & BIT(3)) #define HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(x) ((x) & BIT(3))
/*
* Helper functions to convert 24bit big endian hdcp sequence number to
* host format and back
*/
static inline
u32 drm_hdcp2_seq_num_to_u32(u8 seq_num[HDCP_2_2_SEQ_NUM_LEN])
{
return (u32)(seq_num[2] | seq_num[1] << 8 | seq_num[0] << 16);
}
static inline
void drm_hdcp2_u32_to_seq_num(u8 seq_num[HDCP_2_2_SEQ_NUM_LEN], u32 val)
{
seq_num[0] = val >> 16;
seq_num[1] = val >> 8;
seq_num[2] = val;
}
#endif #endif
...@@ -26,6 +26,11 @@ ...@@ -26,6 +26,11 @@
#include "drm_audio_component.h" #include "drm_audio_component.h"
enum i915_component_type {
I915_COMPONENT_AUDIO = 1,
I915_COMPONENT_HDCP,
};
/* 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
*/ */
......
...@@ -100,4 +100,19 @@ extern struct resource intel_graphics_stolen_res; ...@@ -100,4 +100,19 @@ extern struct resource intel_graphics_stolen_res;
#define INTEL_GEN11_BSM_DW1 0xc4 #define INTEL_GEN11_BSM_DW1 0xc4
#define INTEL_BSM_MASK (-(1u << 20)) #define INTEL_BSM_MASK (-(1u << 20))
enum port {
PORT_NONE = -1,
PORT_A = 0,
PORT_B,
PORT_C,
PORT_D,
PORT_E,
PORT_F,
I915_MAX_PORTS
};
#define port_name(p) ((p) + 'A')
#endif /* _I915_DRM_H_ */ #endif /* _I915_DRM_H_ */
/* SPDX-License-Identifier: (GPL-2.0+) */
/*
* Copyright © 2017-2018 Intel Corporation
*
* Authors:
* Ramalingam C <ramalingam.c@intel.com>
*/
#ifndef _I915_MEI_HDCP_INTERFACE_H_
#define _I915_MEI_HDCP_INTERFACE_H_
#include <linux/mutex.h>
#include <linux/device.h>
#include <drm/drm_hdcp.h>
#include <drm/i915_drm.h>
/**
* enum hdcp_port_type - HDCP port implementation type defined by ME FW
* @HDCP_PORT_TYPE_INVALID: Invalid hdcp port type
* @HDCP_PORT_TYPE_INTEGRATED: In-Host HDCP2.x port
* @HDCP_PORT_TYPE_LSPCON: HDCP2.2 discrete wired Tx port with LSPCON
* (HDMI 2.0) solution
* @HDCP_PORT_TYPE_CPDP: HDCP2.2 discrete wired Tx port using the CPDP (DP 1.3)
* solution
*/
enum hdcp_port_type {
HDCP_PORT_TYPE_INVALID,
HDCP_PORT_TYPE_INTEGRATED,
HDCP_PORT_TYPE_LSPCON,
HDCP_PORT_TYPE_CPDP
};
/**
* enum hdcp_wired_protocol - HDCP adaptation used on the port
* @HDCP_PROTOCOL_INVALID: Invalid HDCP adaptation protocol
* @HDCP_PROTOCOL_HDMI: HDMI adaptation of HDCP used on the port
* @HDCP_PROTOCOL_DP: DP adaptation of HDCP used on the port
*/
enum hdcp_wired_protocol {
HDCP_PROTOCOL_INVALID,
HDCP_PROTOCOL_HDMI,
HDCP_PROTOCOL_DP
};
/**
* struct hdcp_port_data - intel specific HDCP port data
* @port: port index as per I915
* @port_type: HDCP port type as per ME FW classification
* @protocol: HDCP adaptation as per ME FW
* @k: No of streams transmitted on a port. Only on DP MST this is != 1
* @seq_num_m: Count of RepeaterAuth_Stream_Manage msg propagated.
* Initialized to 0 on AKE_INIT. Incremented after every successful
* transmission of RepeaterAuth_Stream_Manage message. When it rolls
* over re-Auth has to be triggered.
* @streams: struct hdcp2_streamid_type[k]. Defines the type and id for the
* streams
*/
struct hdcp_port_data {
enum port port;
u8 port_type;
u8 protocol;
u16 k;
u32 seq_num_m;
struct hdcp2_streamid_type *streams;
};
/**
* struct i915_hdcp_component_ops- ops for HDCP2.2 services.
* @owner: Module providing the ops
* @initiate_hdcp2_session: Initiate a Wired HDCP2.2 Tx Session.
* And Prepare AKE_Init.
* @verify_receiver_cert_prepare_km: Verify the Receiver Certificate
* AKE_Send_Cert and prepare
AKE_Stored_Km/AKE_No_Stored_Km
* @verify_hprime: Verify AKE_Send_H_prime
* @store_pairing_info: Store pairing info received
* @initiate_locality_check: Prepare LC_Init
* @verify_lprime: Verify lprime
* @get_session_key: Prepare SKE_Send_Eks
* @repeater_check_flow_prepare_ack: Validate the Downstream topology
* and prepare rep_ack
* @verify_mprime: Verify mprime
* @enable_hdcp_authentication: Mark a port as authenticated.
* @close_hdcp_session: Close the Wired HDCP Tx session per port.
* This also disables the authenticated state of the port.
*/
struct i915_hdcp_component_ops {
/**
* @owner: mei_hdcp module
*/
struct module *owner;
int (*initiate_hdcp2_session)(struct device *dev,
struct hdcp_port_data *data,
struct hdcp2_ake_init *ake_data);
int (*verify_receiver_cert_prepare_km)(struct device *dev,
struct hdcp_port_data *data,
struct hdcp2_ake_send_cert
*rx_cert,
bool *km_stored,
struct hdcp2_ake_no_stored_km
*ek_pub_km,
size_t *msg_sz);
int (*verify_hprime)(struct device *dev,
struct hdcp_port_data *data,
struct hdcp2_ake_send_hprime *rx_hprime);
int (*store_pairing_info)(struct device *dev,
struct hdcp_port_data *data,
struct hdcp2_ake_send_pairing_info
*pairing_info);
int (*initiate_locality_check)(struct device *dev,
struct hdcp_port_data *data,
struct hdcp2_lc_init *lc_init_data);
int (*verify_lprime)(struct device *dev,
struct hdcp_port_data *data,
struct hdcp2_lc_send_lprime *rx_lprime);
int (*get_session_key)(struct device *dev,
struct hdcp_port_data *data,
struct hdcp2_ske_send_eks *ske_data);
int (*repeater_check_flow_prepare_ack)(struct device *dev,
struct hdcp_port_data *data,
struct hdcp2_rep_send_receiverid_list
*rep_topology,
struct hdcp2_rep_send_ack
*rep_send_ack);
int (*verify_mprime)(struct device *dev,
struct hdcp_port_data *data,
struct hdcp2_rep_stream_ready *stream_ready);
int (*enable_hdcp_authentication)(struct device *dev,
struct hdcp_port_data *data);
int (*close_hdcp_session)(struct device *dev,
struct hdcp_port_data *data);
};
/**
* struct i915_hdcp_component_master - Used for communication between i915
* and mei_hdcp drivers for the HDCP2.2 services
* @mei_dev: device that provide the HDCP2.2 service from MEI Bus.
* @hdcp_ops: Ops implemented by mei_hdcp driver, used by i915 driver.
*/
struct i915_hdcp_comp_master {
struct device *mei_dev;
const struct i915_hdcp_component_ops *ops;
/* To protect the above members. */
struct mutex mutex;
};
#endif /* _I915_MEI_HDCP_INTERFACE_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;
......
...@@ -275,7 +275,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier); ...@@ -275,7 +275,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;
...@@ -294,7 +294,7 @@ int snd_hdac_acomp_init(struct hdac_bus *bus, ...@@ -294,7 +294,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