diff options
Diffstat (limited to 'include/drm')
-rw-r--r-- | include/drm/drm_atomic.h | 3 | ||||
-rw-r--r-- | include/drm/drm_bridge.h | 275 | ||||
-rw-r--r-- | include/drm/drm_dp_helper.h | 8 | ||||
-rw-r--r-- | include/drm/drm_dp_mst_helper.h | 20 | ||||
-rw-r--r-- | include/drm/drm_fb_cma_helper.h | 2 | ||||
-rw-r--r-- | include/drm/gpu_scheduler.h | 8 | ||||
-rw-r--r-- | include/drm/task_barrier.h | 107 |
7 files changed, 144 insertions, 279 deletions
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index ccce65e14917..951dfb15c27b 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -670,9 +670,6 @@ __drm_atomic_get_current_plane_state(struct drm_atomic_state *state, } int __must_check -drm_atomic_add_encoder_bridges(struct drm_atomic_state *state, - struct drm_encoder *encoder); -int __must_check drm_atomic_add_affected_connectors(struct drm_atomic_state *state, struct drm_crtc *crtc); int __must_check diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 46e15526b087..694e153a7531 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -25,8 +25,6 @@ #include <linux/list.h> #include <linux/ctype.h> - -#include <drm/drm_atomic.h> #include <drm/drm_encoder.h> #include <drm/drm_mode_object.h> #include <drm/drm_modes.h> @@ -36,65 +34,6 @@ struct drm_bridge_timings; struct drm_panel; /** - * struct drm_bus_cfg - bus configuration - * - * This structure stores the configuration of a physical bus between two - * components in an output pipeline, usually between two bridges, an encoder - * and a bridge, or a bridge and a connector. - * - * The bus configuration is stored in &drm_bridge_state separately for the - * input and output buses, as seen from the point of view of each bridge. The - * bus configuration of a bridge output is usually identical to the - * configuration of the next bridge's input, but may differ if the signals are - * modified between the two bridges, for instance by an inverter on the board. - * The input and output configurations of a bridge may differ if the bridge - * modifies the signals internally, for instance by performing format - * conversion, or modifying signals polarities. - */ -struct drm_bus_cfg { - /** - * @format: format used on this bus (one of the MEDIA_BUS_FMT_* format) - * - * This field should not be directly modified by drivers - * (&drm_atomic_bridge_chain_select_bus_fmts() takes care of the bus - * format negotiation). - */ - u32 format; - - /** - * @flags: DRM_BUS_* flags used on this bus - */ - u32 flags; -}; - -/** - * struct drm_bridge_state - Atomic bridge state object - * @base: inherit from &drm_private_state - * @bridge: the bridge this state refers to - */ -struct drm_bridge_state { - struct drm_private_state base; - - struct drm_bridge *bridge; - - /** - * @input_bus_cfg: input bus configuration - */ - struct drm_bus_cfg input_bus_cfg; - - /** - * @output_bus_cfg: input bus configuration - */ - struct drm_bus_cfg output_bus_cfg; -}; - -static inline struct drm_bridge_state * -drm_priv_to_bridge_state(struct drm_private_state *priv) -{ - return container_of(priv, struct drm_bridge_state, base); -} - -/** * struct drm_bridge_funcs - drm_bridge control functions */ struct drm_bridge_funcs { @@ -170,9 +109,7 @@ struct drm_bridge_funcs { * this function passes all other callbacks must succeed for this * configuration. * - * The mode_fixup callback is optional. &drm_bridge_funcs.mode_fixup() - * is not called when &drm_bridge_funcs.atomic_check() is implemented, - * so only one of them should be provided. + * The @mode_fixup callback is optional. * * NOTE: * @@ -326,7 +263,7 @@ struct drm_bridge_funcs { * The @atomic_pre_enable callback is optional. */ void (*atomic_pre_enable)(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state); + struct drm_atomic_state *old_state); /** * @atomic_enable: @@ -351,7 +288,7 @@ struct drm_bridge_funcs { * The @atomic_enable callback is optional. */ void (*atomic_enable)(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state); + struct drm_atomic_state *old_state); /** * @atomic_disable: * @@ -374,7 +311,7 @@ struct drm_bridge_funcs { * The @atomic_disable callback is optional. */ void (*atomic_disable)(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state); + struct drm_atomic_state *old_state); /** * @atomic_post_disable: @@ -400,146 +337,7 @@ struct drm_bridge_funcs { * The @atomic_post_disable callback is optional. */ void (*atomic_post_disable)(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state); - - /** - * @atomic_duplicate_state: - * - * Duplicate the current bridge state object (which is guaranteed to be - * non-NULL). - * - * The atomic_duplicate_state() is optional. When not implemented the - * core allocates a drm_bridge_state object and calls - * &__drm_atomic_helper_bridge_duplicate_state() to initialize it. - * - * RETURNS: - * A valid drm_bridge_state object or NULL if the allocation fails. - */ - struct drm_bridge_state *(*atomic_duplicate_state)(struct drm_bridge *bridge); - - /** - * @atomic_destroy_state: - * - * Destroy a bridge state object previously allocated by - * &drm_bridge_funcs.atomic_duplicate_state(). - * - * The atomic_destroy_state hook is optional. When not implemented the - * core calls kfree() on the state. - */ - void (*atomic_destroy_state)(struct drm_bridge *bridge, - struct drm_bridge_state *state); - - /** - * @atomic_get_output_bus_fmts: - * - * Return the supported bus formats on the output end of a bridge. - * The returned array must be allocated with kmalloc() and will be - * freed by the caller. If the allocation fails, NULL should be - * returned. num_output_fmts must be set to the returned array size. - * Formats listed in the returned array should be listed in decreasing - * preference order (the core will try all formats until it finds one - * that works). - * - * This method is only called on the last element of the bridge chain - * as part of the bus format negotiation process that happens in - * &drm_atomic_bridge_chain_select_bus_fmts(). - * This method is optional. When not implemented, the core will - * fall back to &drm_connector.display_info.bus_formats[0] if - * &drm_connector.display_info.num_bus_formats > 0, - * or to MEDIA_BUS_FMT_FIXED otherwise. - */ - u32 *(*atomic_get_output_bus_fmts)(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state, - unsigned int *num_output_fmts); - - /** - * @atomic_get_input_bus_fmts: - * - * Return the supported bus formats on the input end of a bridge for - * a specific output bus format. - * - * The returned array must be allocated with kmalloc() and will be - * freed by the caller. If the allocation fails, NULL should be - * returned. num_output_fmts must be set to the returned array size. - * Formats listed in the returned array should be listed in decreasing - * preference order (the core will try all formats until it finds one - * that works). When the format is not supported NULL should be - * returned and *num_output_fmts should be set to 0. - * - * This method is called on all elements of the bridge chain as part of - * the bus format negotiation process that happens in - * &drm_atomic_bridge_chain_select_bus_fmts(). - * This method is optional. When not implemented, the core will bypass - * bus format negotiation on this element of the bridge without - * failing, and the previous element in the chain will be passed - * MEDIA_BUS_FMT_FIXED as its output bus format. - * - * Bridge drivers that need to support being linked to bridges that are - * not supporting bus format negotiation should handle the - * output_fmt == MEDIA_BUS_FMT_FIXED case appropriately, by selecting a - * sensible default value or extracting this information from somewhere - * else (FW property, &drm_display_mode, &drm_display_info, ...) - * - * Note: Even if input format selection on the first bridge has no - * impact on the negotiation process (bus format negotiation stops once - * we reach the first element of the chain), drivers are expected to - * return accurate input formats as the input format may be used to - * configure the CRTC output appropriately. - */ - u32 *(*atomic_get_input_bus_fmts)(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state, - u32 output_fmt, - unsigned int *num_input_fmts); - - /** - * @atomic_check: - * - * This method is responsible for checking bridge state correctness. - * It can also check the state of the surrounding components in chain - * to make sure the whole pipeline can work properly. - * - * &drm_bridge_funcs.atomic_check() hooks are called in reverse - * order (from the last to the first bridge). - * - * This method is optional. &drm_bridge_funcs.mode_fixup() is not - * called when &drm_bridge_funcs.atomic_check() is implemented, so only - * one of them should be provided. - * - * If drivers need to tweak &drm_bridge_state.input_bus_cfg.flags or - * &drm_bridge_state.output_bus_cfg.flags it should should happen in - * this function. By default the &drm_bridge_state.output_bus_cfg.flags - * field is set to the next bridge - * &drm_bridge_state.input_bus_cfg.flags value or - * &drm_connector.display_info.bus_flags if the bridge is the last - * element in the chain. - * - * RETURNS: - * zero if the check passed, a negative error code otherwise. - */ - int (*atomic_check)(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state); - - /** - * @atomic_reset: - * - * Reset the bridge to a predefined state (or retrieve its current - * state) and return a &drm_bridge_state object matching this state. - * This function is called at attach time. - * - * The atomic_reset hook is optional. When not implemented the core - * allocates a new state and calls &__drm_atomic_helper_bridge_reset(). - * - * RETURNS: - * A valid drm_bridge_state object in case of success, an ERR_PTR() - * giving the reason of the failure otherwise. - */ - struct drm_bridge_state *(*atomic_reset)(struct drm_bridge *bridge); + struct drm_atomic_state *old_state); }; /** @@ -582,8 +380,6 @@ struct drm_bridge_timings { * struct drm_bridge - central DRM bridge control structure */ struct drm_bridge { - /** @base: inherit from &drm_private_object */ - struct drm_private_obj base; /** @dev: DRM device this bridge belongs to */ struct drm_device *dev; /** @encoder: encoder to which this bridge is connected */ @@ -608,12 +404,6 @@ struct drm_bridge { void *driver_private; }; -static inline struct drm_bridge * -drm_priv_to_bridge(struct drm_private_obj *priv) -{ - return container_of(priv, struct drm_bridge, base); -} - void drm_bridge_add(struct drm_bridge *bridge); void drm_bridge_remove(struct drm_bridge *bridge); struct drm_bridge *of_drm_find_bridge(struct device_node *np); @@ -692,9 +482,6 @@ void drm_bridge_chain_mode_set(struct drm_bridge *bridge, void drm_bridge_chain_pre_enable(struct drm_bridge *bridge); void drm_bridge_chain_enable(struct drm_bridge *bridge); -int drm_atomic_bridge_chain_check(struct drm_bridge *bridge, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state); void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge, struct drm_atomic_state *state); void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge, @@ -704,58 +491,6 @@ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge, void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge, struct drm_atomic_state *state); -u32 * -drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state, - u32 output_fmt, - unsigned int *num_input_fmts); - -void __drm_atomic_helper_bridge_reset(struct drm_bridge *bridge, - struct drm_bridge_state *state); -void __drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge, - struct drm_bridge_state *new); - -static inline struct drm_bridge_state * -drm_atomic_get_bridge_state(struct drm_atomic_state *state, - struct drm_bridge *bridge) -{ - struct drm_private_state *obj_state; - - obj_state = drm_atomic_get_private_obj_state(state, &bridge->base); - if (IS_ERR(obj_state)) - return ERR_CAST(obj_state); - - return drm_priv_to_bridge_state(obj_state); -} - -static inline struct drm_bridge_state * -drm_atomic_get_old_bridge_state(struct drm_atomic_state *state, - struct drm_bridge *bridge) -{ - struct drm_private_state *obj_state; - - obj_state = drm_atomic_get_old_private_obj_state(state, &bridge->base); - if (!obj_state) - return NULL; - - return drm_priv_to_bridge_state(obj_state); -} - -static inline struct drm_bridge_state * -drm_atomic_get_new_bridge_state(struct drm_atomic_state *state, - struct drm_bridge *bridge) -{ - struct drm_private_state *obj_state; - - obj_state = drm_atomic_get_new_private_obj_state(state, &bridge->base); - if (!obj_state) - return NULL; - - return drm_priv_to_bridge_state(obj_state); -} - #ifdef CONFIG_DRM_PANEL_BRIDGE struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel); struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel, diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 8f8f3632e697..bc04467f7c3a 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1465,6 +1465,7 @@ int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]); void drm_dp_downstream_debug(struct seq_file *m, const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4], struct drm_dp_aux *aux); +void drm_dp_remote_aux_init(struct drm_dp_aux *aux); void drm_dp_aux_init(struct drm_dp_aux *aux); int drm_dp_aux_register(struct drm_dp_aux *aux); void drm_dp_aux_unregister(struct drm_dp_aux *aux); @@ -1522,6 +1523,13 @@ enum drm_dp_quirk { * The driver should ignore SINK_COUNT during detection. */ DP_DPCD_QUIRK_NO_SINK_COUNT, + /** + * @DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD: + * + * The device supports MST DSC despite not supporting Virtual DPCD. + * The DSC caps can be read from the physical aux instead. + */ + DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD, }; /** diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 5699493c6fb1..e5503771232f 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -156,6 +156,8 @@ struct drm_dp_mst_port { * audio-capable. */ bool has_audio; + + bool fec_capable; }; /** @@ -383,6 +385,7 @@ struct drm_dp_port_number_req { struct drm_dp_enum_path_resources_ack_reply { u8 port_number; + bool fec_capable; u16 full_payload_bw_number; u16 avail_payload_bw_number; }; @@ -499,6 +502,8 @@ struct drm_dp_payload { struct drm_dp_vcpi_allocation { struct drm_dp_mst_port *port; int vcpi; + int pbn; + bool dsc_enabled; struct list_head next; }; @@ -727,8 +732,7 @@ bool drm_dp_mst_port_has_audio(struct drm_dp_mst_topology_mgr *mgr, struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); -int drm_dp_calc_pbn_mode(int clock, int bpp); - +int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc); bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int pbn, int slots); @@ -777,7 +781,15 @@ struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_a int __must_check drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, int pbn); + struct drm_dp_mst_port *port, int pbn, + int pbn_div); +int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, + struct drm_dp_mst_port *port, + int pbn, int pbn_div, + bool enable); +int __must_check +drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, + struct drm_dp_mst_topology_mgr *mgr); int __must_check drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, @@ -789,6 +801,8 @@ int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state); void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port); void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port); +struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port); + extern const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs; /** diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h index 4becb09975a4..795aea1d0a25 100644 --- a/include/drm/drm_fb_cma_helper.h +++ b/include/drm/drm_fb_cma_helper.h @@ -2,6 +2,8 @@ #ifndef __DRM_FB_CMA_HELPER_H__ #define __DRM_FB_CMA_HELPER_H__ +#include <linux/types.h> + struct drm_framebuffer; struct drm_plane_state; diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index 684692a8ed76..96a1a1b7526e 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -81,8 +81,9 @@ enum drm_sched_priority { struct drm_sched_entity { struct list_head list; struct drm_sched_rq *rq; - struct drm_sched_rq **rq_list; - unsigned int num_rq_list; + unsigned int num_sched_list; + struct drm_gpu_scheduler **sched_list; + enum drm_sched_priority priority; spinlock_t rq_lock; struct spsc_queue job_queue; @@ -312,7 +313,8 @@ void drm_sched_rq_remove_entity(struct drm_sched_rq *rq, struct drm_sched_entity *entity); int drm_sched_entity_init(struct drm_sched_entity *entity, - struct drm_sched_rq **rq_list, + enum drm_sched_priority priority, + struct drm_gpu_scheduler **sched_list, unsigned int num_rq_list, atomic_t *guilty); long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout); diff --git a/include/drm/task_barrier.h b/include/drm/task_barrier.h new file mode 100644 index 000000000000..087e3f649c52 --- /dev/null +++ b/include/drm/task_barrier.h @@ -0,0 +1,107 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include <linux/semaphore.h> +#include <linux/atomic.h> + +/* + * Reusable 2 PHASE task barrier (randevouz point) implementation for N tasks. + * Based on the Little book of sempahores - https://greenteapress.com/wp/semaphores/ + */ + + + +#ifndef DRM_TASK_BARRIER_H_ +#define DRM_TASK_BARRIER_H_ + +/* + * Represents an instance of a task barrier. + */ +struct task_barrier { + unsigned int n; + atomic_t count; + struct semaphore enter_turnstile; + struct semaphore exit_turnstile; +}; + +static inline void task_barrier_signal_turnstile(struct semaphore *turnstile, + unsigned int n) +{ + int i; + + for (i = 0 ; i < n; i++) + up(turnstile); +} + +static inline void task_barrier_init(struct task_barrier *tb) +{ + tb->n = 0; + atomic_set(&tb->count, 0); + sema_init(&tb->enter_turnstile, 0); + sema_init(&tb->exit_turnstile, 0); +} + +static inline void task_barrier_add_task(struct task_barrier *tb) +{ + tb->n++; +} + +static inline void task_barrier_rem_task(struct task_barrier *tb) +{ + tb->n--; +} + +/* + * Lines up all the threads BEFORE the critical point. + * + * When all thread passed this code the entry barrier is back to locked state. + */ +static inline void task_barrier_enter(struct task_barrier *tb) +{ + if (atomic_inc_return(&tb->count) == tb->n) + task_barrier_signal_turnstile(&tb->enter_turnstile, tb->n); + + down(&tb->enter_turnstile); +} + +/* + * Lines up all the threads AFTER the critical point. + * + * This function is used to avoid any one thread running ahead if the barrier is + * used repeatedly . + */ +static inline void task_barrier_exit(struct task_barrier *tb) +{ + if (atomic_dec_return(&tb->count) == 0) + task_barrier_signal_turnstile(&tb->exit_turnstile, tb->n); + + down(&tb->exit_turnstile); +} + +/* Convinieince function when nothing to be done in between entry and exit */ +static inline void task_barrier_full(struct task_barrier *tb) +{ + task_barrier_enter(tb); + task_barrier_exit(tb); +} + +#endif |