@@ -58,13 +58,17 @@ struct mtk_crtc {
wait_queue_head_t cb_blocking_queue;
#endif
- struct device *mmsys_dev;
+ struct device *mmsys_dev[MAX_MMSYS];
struct device *dma_dev;
- struct mtk_mutex *mutex;
+ struct device *vdisp_ao_dev;
+ struct mtk_mutex *mutex[MAX_MMSYS];
unsigned int ddp_comp_nr;
struct mtk_ddp_comp **ddp_comp;
+ enum mtk_drm_mmsys *ddp_comp_sys;
+ bool exist[MAX_MMSYS];
unsigned int num_conn_routes;
const struct mtk_drm_route *conn_routes;
+ enum mtk_drm_mmsys conn_routes_sys;
/* lock for display hardware access */
struct mutex hw_lock;
@@ -82,6 +86,11 @@ struct mtk_crtc_state {
unsigned int pending_vrefresh;
};
+struct mtk_crtc_comp_info {
+ enum mtk_drm_mmsys sys;
+ unsigned int comp_id;
+};
+
static inline struct mtk_crtc *to_mtk_crtc(struct drm_crtc *c)
{
return container_of(c, struct mtk_crtc, base);
@@ -125,7 +134,9 @@ static void mtk_crtc_destroy(struct drm_crtc *crtc)
struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
int i;
- mtk_mutex_put(mtk_crtc->mutex);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->mutex[i])
+ mtk_mutex_put(mtk_crtc->mutex[i]);
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
if (mtk_crtc->cmdq_client.chan) {
cmdq_pkt_destroy(&mtk_crtc->cmdq_client, &mtk_crtc->cmdq_handle);
@@ -223,7 +234,14 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_crtc *mtk_crtc)
int i;
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
+ enum mtk_drm_mmsys mmsys;
+
ret = mtk_ddp_comp_clk_enable(mtk_crtc->ddp_comp[i]);
+ if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]->id) == MTK_DISP_VIRTUAL) {
+ mmsys = mtk_crtc->ddp_comp_sys[i];
+ ret = mtk_mmsys_ddp_clk_enable(mtk_crtc->mmsys_dev[mmsys],
+ mtk_crtc->ddp_comp[i]->id);
+ }
if (ret) {
DRM_ERROR("Failed to enable clock %d: %d\n", i, ret);
goto err;
@@ -232,17 +250,28 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_crtc *mtk_crtc)
return 0;
err:
- while (--i >= 0)
+ while (--i >= 0) {
mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
+ if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]->id) == MTK_DISP_VIRTUAL)
+ mtk_mmsys_ddp_clk_disable(mtk_crtc->mmsys_dev[mtk_crtc->ddp_comp_sys[i]],
+ mtk_crtc->ddp_comp[i]->id);
+ }
return ret;
}
static void mtk_crtc_ddp_clk_disable(struct mtk_crtc *mtk_crtc)
{
int i;
+ enum mtk_drm_mmsys mmsys;
- for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
+ for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
+ if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]->id) == MTK_DISP_VIRTUAL) {
+ mmsys = mtk_crtc->ddp_comp_sys[i];
+ mtk_mmsys_ddp_clk_disable(mtk_crtc->mmsys_dev[mmsys],
+ mtk_crtc->ddp_comp[i]->id);
+ }
+ }
}
static
@@ -332,7 +361,8 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
struct drm_connector_list_iter conn_iter;
unsigned int width, height, vrefresh, bpc = MTK_MAX_BPC;
int ret;
- int i;
+ int i, j;
+ enum mtk_drm_mmsys mmsys;
if (WARN_ON(!crtc->state))
return -EINVAL;
@@ -362,10 +392,18 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
return ret;
}
- ret = mtk_mutex_prepare(mtk_crtc->mutex);
- if (ret < 0) {
- DRM_ERROR("Failed to enable mutex clock: %d\n", ret);
- goto err_pm_runtime_put;
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i])
+ mtk_mmsys_top_clk_enable(mtk_crtc->mmsys_dev[i]);
+
+ for (i = 0; i < MAX_MMSYS; i++) {
+ if (!mtk_crtc->mutex[i] || !mtk_crtc->exist[i])
+ continue;
+ ret = mtk_mutex_prepare(mtk_crtc->mutex[i]);
+ if (ret < 0) {
+ DRM_ERROR("Failed to enable mmsys%d mutex clock: %d\n", i, ret);
+ goto err_pm_runtime_put;
+ }
}
ret = mtk_crtc_ddp_clk_enable(mtk_crtc);
@@ -374,19 +412,36 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
goto err_mutex_unprepare;
}
+ if (mtk_crtc->vdisp_ao_dev)
+ mtk_mmsys_default_config(mtk_crtc->vdisp_ao_dev);
+
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i])
+ mtk_mmsys_default_config(mtk_crtc->mmsys_dev[i]);
+
for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
- if (!mtk_ddp_comp_connect(mtk_crtc->ddp_comp[i], mtk_crtc->mmsys_dev,
+ mmsys = mtk_crtc->ddp_comp_sys[i];
+ if (!mtk_ddp_comp_connect(mtk_crtc->ddp_comp[i], mtk_crtc->mmsys_dev[mmsys],
mtk_crtc->ddp_comp[i + 1]->id))
- mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev,
+ mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev[mmsys],
mtk_crtc->ddp_comp[i]->id,
mtk_crtc->ddp_comp[i + 1]->id);
- if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
- mtk_mutex_add_comp(mtk_crtc->mutex,
+ if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+ mtk_mutex_add_comp(mtk_crtc->mutex[mmsys],
mtk_crtc->ddp_comp[i]->id);
}
- if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
- mtk_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
- mtk_mutex_enable(mtk_crtc->mutex);
+ mmsys = mtk_crtc->ddp_comp_sys[i];
+ if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+ mtk_mutex_add_comp(mtk_crtc->mutex[mmsys], mtk_crtc->ddp_comp[i]->id);
+
+ /* Need to set sof source for all mmsys mutexs in this crtc */
+ for (j = 0; j < MAX_MMSYS; j++)
+ if (mtk_crtc->exist[j] && mtk_crtc->mutex[j])
+ mtk_mutex_write_comp_sof(mtk_crtc->mutex[j], mtk_crtc->ddp_comp[i]->id);
+
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+ mtk_mutex_enable(mtk_crtc->mutex[i]);
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[i];
@@ -394,7 +449,11 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
if (i == 1)
mtk_ddp_comp_bgclr_in_on(comp);
- mtk_ddp_comp_config(comp, width, height, vrefresh, bpc, NULL);
+ if (mtk_ddp_comp_get_type(comp->id) == MTK_DISP_VIRTUAL)
+ mtk_mmsys_ddp_config(mtk_crtc->mmsys_dev[mtk_crtc->ddp_comp_sys[i]],
+ comp->id, width, height, NULL);
+ else
+ mtk_ddp_comp_config(comp, width, height, vrefresh, bpc, NULL);
mtk_ddp_comp_start(comp);
}
@@ -418,7 +477,10 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
return 0;
err_mutex_unprepare:
- mtk_mutex_unprepare(mtk_crtc->mutex);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+ mtk_mutex_unprepare(mtk_crtc->mutex[i]);
+
err_pm_runtime_put:
pm_runtime_put(crtc->dev->dev);
return ret;
@@ -430,6 +492,7 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc)
struct drm_crtc *crtc = &mtk_crtc->base;
unsigned long flags;
int i;
+ enum mtk_drm_mmsys mmsys;
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
@@ -437,27 +500,46 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc)
mtk_ddp_comp_bgclr_in_off(mtk_crtc->ddp_comp[i]);
}
- for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
- if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
- mtk_mutex_remove_comp(mtk_crtc->mutex,
+ for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
+ mmsys = mtk_crtc->ddp_comp_sys[i];
+ if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+ mtk_mutex_remove_comp(mtk_crtc->mutex[mtk_crtc->ddp_comp_sys[i]],
mtk_crtc->ddp_comp[i]->id);
- mtk_mutex_disable(mtk_crtc->mutex);
+ }
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+ mtk_mutex_disable(mtk_crtc->mutex[i]);
+
for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
- if (!mtk_ddp_comp_disconnect(mtk_crtc->ddp_comp[i], mtk_crtc->mmsys_dev,
- mtk_crtc->ddp_comp[i + 1]->id))
- mtk_mmsys_ddp_disconnect(mtk_crtc->mmsys_dev,
- mtk_crtc->ddp_comp[i]->id,
- mtk_crtc->ddp_comp[i + 1]->id);
- if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
- mtk_mutex_remove_comp(mtk_crtc->mutex,
+ struct mtk_ddp_comp *comp;
+ unsigned int curr, next;
+
+ comp = mtk_crtc->ddp_comp[i];
+ curr = mtk_crtc->ddp_comp[i]->id;
+ next = mtk_crtc->ddp_comp[i + 1]->id;
+ mmsys = mtk_crtc->ddp_comp_sys[i];
+ if (!mtk_ddp_comp_disconnect(comp, mtk_crtc->mmsys_dev[mmsys], next))
+ mtk_mmsys_ddp_disconnect(mtk_crtc->mmsys_dev[mmsys], curr, next);
+ if (!mtk_ddp_comp_remove(comp, mtk_crtc->mutex[mmsys]))
+ mtk_mutex_remove_comp(mtk_crtc->mutex[mtk_crtc->ddp_comp_sys[i]],
mtk_crtc->ddp_comp[i]->id);
}
- if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
- mtk_mutex_remove_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
+
+ mmsys = mtk_crtc->ddp_comp_sys[i];
+ if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+ mtk_mutex_remove_comp(mtk_crtc->mutex[mmsys], mtk_crtc->ddp_comp[i]->id);
+
mtk_crtc_ddp_clk_disable(mtk_crtc);
- mtk_mutex_unprepare(mtk_crtc->mutex);
- pm_runtime_put(drm->dev);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+ mtk_mutex_unprepare(mtk_crtc->mutex[i]);
+
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i])
+ mtk_mmsys_top_clk_disable(mtk_crtc->mmsys_dev[i]);
+
+ pm_runtime_put_sync(drm->dev);
if (crtc->state->event && !crtc->state->active) {
spin_lock_irqsave(&crtc->dev->event_lock, flags);
@@ -581,9 +663,15 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank)
mtk_crtc->pending_async_planes = true;
if (priv->data->shadow_register) {
- mtk_mutex_acquire(mtk_crtc->mutex);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+ mtk_mutex_acquire(mtk_crtc->mutex[i]);
+
mtk_crtc_ddp_config(crtc, NULL);
- mtk_mutex_release(mtk_crtc->mutex);
+
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+ mtk_mutex_release(mtk_crtc->mutex[i]);
}
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
if (mtk_crtc->cmdq_client.chan) {
@@ -659,6 +747,7 @@ static void mtk_crtc_update_output(struct drm_crtc *crtc,
{
int crtc_index = drm_crtc_index(crtc);
int i;
+ unsigned int mmsys;
struct device *dev;
struct drm_crtc_state *crtc_state = state->crtcs[crtc_index].new_state;
struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
@@ -671,7 +760,8 @@ static void mtk_crtc_update_output(struct drm_crtc *crtc,
if (!mtk_crtc->num_conn_routes)
return;
- priv = ((struct mtk_drm_private *)crtc->dev->dev_private)->all_drm_private[crtc_index];
+ mmsys = mtk_crtc->conn_routes_sys;
+ priv = ((struct mtk_drm_private *)crtc->dev->dev_private)->all_drm_private[mmsys];
dev = priv->dev;
dev_dbg(dev, "connector change:%d, encoder mask:0x%x for crtc:%d\n",
@@ -684,6 +774,8 @@ static void mtk_crtc_update_output(struct drm_crtc *crtc,
if (comp->encoder_index >= 0 &&
(encoder_mask & BIT(comp->encoder_index))) {
mtk_crtc->ddp_comp[mtk_crtc->ddp_comp_nr - 1] = comp;
+ mtk_crtc->ddp_comp_sys[mtk_crtc->ddp_comp_nr - 1] = mmsys;
+ mtk_crtc->exist[mmsys] = true;
dev_dbg(dev, "Add comp_id: %d at path index %d\n",
comp->id, mtk_crtc->ddp_comp_nr - 1);
break;
@@ -720,13 +812,35 @@ static void mtk_crtc_atomic_enable(struct drm_crtc *crtc,
struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
int ret;
+ int i, j;
+ int mmsys_cnt = 0;
DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
- ret = mtk_ddp_comp_power_on(comp);
- if (ret < 0) {
- DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", ret);
- return;
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i])
+ mmsys_cnt++;
+
+ if (mmsys_cnt == 1) {
+ ret = pm_runtime_resume_and_get(comp->dev);
+ if (ret < 0) {
+ DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", ret);
+ return;
+ }
+ } else {
+ for (i = 0; i < MAX_MMSYS; i++) {
+ if (!mtk_crtc->exist[i])
+ continue;
+ ret = pm_runtime_resume_and_get(mtk_crtc->mmsys_dev[i]);
+ if (ret < 0) {
+ DRM_DEV_ERROR(mtk_crtc->mmsys_dev[i],
+ "Failed to enable power domain: %d\n", ret);
+ for (j = i - 1; j >= 0; j--)
+ if (mtk_crtc->exist[i])
+ pm_runtime_put(comp->dev);
+ return;
+ }
+ }
}
mtk_crtc_update_output(crtc, state);
@@ -746,12 +860,17 @@ static void mtk_crtc_atomic_disable(struct drm_crtc *crtc,
{
struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
- int i;
+ int i, ret;
+ int mmsys_cnt = 0;
DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
if (!mtk_crtc->enabled)
return;
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i])
+ mmsys_cnt++;
+
/* Set all pending plane state to disabled */
for (i = 0; i < mtk_crtc->layer_nr; i++) {
struct drm_plane *plane = &mtk_crtc->planes[i];
@@ -776,7 +895,21 @@ static void mtk_crtc_atomic_disable(struct drm_crtc *crtc,
drm_crtc_vblank_off(crtc);
mtk_crtc_ddp_hw_fini(mtk_crtc);
- mtk_ddp_comp_power_off(comp);
+
+ if (mmsys_cnt > 1) {
+ for (i = 0; i < MAX_MMSYS; i++) {
+ if (mtk_crtc->exist[i]) {
+ ret = pm_runtime_put(mtk_crtc->mmsys_dev[i]);
+ if (ret < 0)
+ DRM_DEV_ERROR(mtk_crtc->mmsys_dev[i],
+ "Failed to disable power domain: %d\n", ret);
+ }
+ }
+ } else {
+ ret = pm_runtime_put(comp->dev);
+ if (ret < 0)
+ DRM_DEV_ERROR(comp->dev, "Failed to disable power domain: %d\n", ret);
+ }
mtk_crtc->enabled = false;
}
@@ -937,49 +1070,108 @@ struct device *mtk_crtc_dma_dev_get(struct drm_crtc *crtc)
return mtk_crtc->dma_dev;
}
-int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
- unsigned int path_len, int priv_data_index,
- const struct mtk_drm_route *conn_routes,
- unsigned int num_conn_routes)
+int mtk_crtc_create(struct drm_device *drm_dev, enum mtk_crtc_path path_sel)
{
struct mtk_drm_private *priv = drm_dev->dev_private;
struct device *dev = drm_dev->dev;
struct mtk_crtc *mtk_crtc;
unsigned int num_comp_planes = 0;
int ret;
- int i;
+ int i, j, k;
bool has_ctm = false;
uint gamma_lut_size = 0;
struct drm_crtc *tmp;
int crtc_i = 0;
-
- if (!path)
- return 0;
-
- priv = priv->all_drm_private[priv_data_index];
+ struct mtk_drm_private *subsys_priv;
+ struct mtk_crtc_comp_info path[DDP_COMPONENT_ID_MAX];
+ unsigned int path_len = 0;
+ const struct mtk_drm_route *conn_routes = NULL;
+ unsigned int num_conn_routes = 0;
+ enum mtk_drm_mmsys conn_mmsys;
drm_for_each_crtc(tmp, drm_dev)
crtc_i++;
+ for (j = 0; j < priv->data->mmsys_dev_num; j++) {
+ for (k = 0; k < MAX_MMSYS; k++) {
+ const unsigned int *subsys_path;
+ unsigned int subsys_path_len;
+ unsigned int order = 0;
+
+ subsys_priv = priv->all_drm_private[k];
+ if (!subsys_priv)
+ continue;
+
+ if (path_sel == CRTC_MAIN) {
+ subsys_path = subsys_priv->data->main_path;
+ subsys_path_len = subsys_priv->data->main_len;
+ order = subsys_priv->data->main_order;
+ } else if (path_sel == CRTC_EXT) {
+ subsys_path = subsys_priv->data->ext_path;
+ subsys_path_len = subsys_priv->data->ext_len;
+ order = subsys_priv->data->ext_order;
+ } else if (path_sel == CRTC_THIRD) {
+ subsys_path = subsys_priv->data->third_path;
+ subsys_path_len = subsys_priv->data->third_len;
+ order = subsys_priv->data->third_order;
+ }
+
+ if (subsys_priv->data->num_conn_routes) {
+ conn_routes = subsys_priv->data->conn_routes;
+ num_conn_routes = subsys_priv->data->num_conn_routes;
+ conn_mmsys = subsys_priv->data->mmsys_id;
+ }
+
+ if (j != order)
+ continue;
+ if (!subsys_path_len)
+ continue;
+
+ for (i = 0; i < subsys_path_len; i++) {
+ path[path_len].sys = subsys_priv->data->mmsys_id;
+ path[path_len].comp_id = subsys_path[i];
+ path_len++;
+ }
+ }
+ }
+
+ if (!path_len)
+ return 0;
+
+ if (num_conn_routes) {
+ for (i = 0; i < num_conn_routes; i++)
+ if (conn_routes->crtc_id == crtc_i)
+ break;
+ if (i == num_conn_routes) {
+ num_conn_routes = 0;
+ conn_routes = NULL;
+ }
+ }
+
for (i = 0; i < path_len; i++) {
- enum mtk_ddp_comp_id comp_id = path[i];
+ enum mtk_ddp_comp_id comp_id = path[i].comp_id;
struct device_node *node;
struct mtk_ddp_comp *comp;
+ priv = priv->all_drm_private[path[i].sys];
node = priv->comp_node[comp_id];
comp = &priv->ddp_comp[comp_id];
/* Not all drm components have a DTS device node, such as ovl_adaptor,
* which is the drm bring up sub driver
*/
- if (!node && comp_id != DDP_COMPONENT_DRM_OVL_ADAPTOR) {
+ if (!node && comp_id != DDP_COMPONENT_DRM_OVL_ADAPTOR &&
+ comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 &&
+ comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 &&
+ comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 &&
+ mtk_ddp_comp_get_type(comp_id) != MTK_DISP_VIRTUAL) {
dev_info(dev,
"Not creating crtc %d because component %d is disabled or missing\n",
crtc_i, comp_id);
return 0;
}
- if (!comp->dev) {
+ if (!comp->dev && mtk_ddp_comp_get_type(comp_id) != MTK_DISP_VIRTUAL) {
dev_err(dev, "Component %pOF not initialized\n", node);
return -ENODEV;
}
@@ -989,7 +1181,9 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
if (!mtk_crtc)
return -ENOMEM;
- mtk_crtc->mmsys_dev = priv->mmsys_dev;
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (priv->all_drm_private[i])
+ mtk_crtc->mmsys_dev[i] = priv->all_drm_private[i]->mmsys_dev;
mtk_crtc->ddp_comp_nr = path_len;
mtk_crtc->ddp_comp = devm_kcalloc(dev,
mtk_crtc->ddp_comp_nr + (conn_routes ? 1 : 0),
@@ -998,19 +1192,36 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
if (!mtk_crtc->ddp_comp)
return -ENOMEM;
- mtk_crtc->mutex = mtk_mutex_get(priv->mutex_dev);
- if (IS_ERR(mtk_crtc->mutex)) {
- ret = PTR_ERR(mtk_crtc->mutex);
- dev_err(dev, "Failed to get mutex: %d\n", ret);
- return ret;
+ mtk_crtc->ddp_comp_sys = devm_kmalloc_array(dev, mtk_crtc->ddp_comp_nr +
+ (conn_routes ? 1 : 0),
+ sizeof(mtk_crtc->ddp_comp_sys), GFP_KERNEL);
+ if (!mtk_crtc->ddp_comp_sys)
+ return -ENOMEM;
+
+ for (i = 0; i < MAX_MMSYS; i++) {
+ if (!priv->all_drm_private[i])
+ continue;
+
+ priv = priv->all_drm_private[i];
+ mtk_crtc->mutex[i] = mtk_mutex_get(priv->mutex_dev);
+ if (IS_ERR(mtk_crtc->mutex[i])) {
+ ret = PTR_ERR(mtk_crtc->mutex[i]);
+ dev_err(dev, "Failed to get mutex: %d\n", ret);
+ return ret;
+ }
}
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
- unsigned int comp_id = path[i];
+ unsigned int comp_id = path[i].comp_id;
struct mtk_ddp_comp *comp;
+ priv = priv->all_drm_private[path[i].sys];
comp = &priv->ddp_comp[comp_id];
+ if (mtk_ddp_comp_get_type(comp_id) == MTK_DISP_VIRTUAL)
+ comp->id = comp_id;
mtk_crtc->ddp_comp[i] = comp;
+ mtk_crtc->ddp_comp_sys[i] = path[i].sys;
+ mtk_crtc->exist[path[i].sys] = true;
if (comp->funcs) {
if (comp->funcs->gamma_set && comp->funcs->gamma_get_lut_size) {
@@ -1047,8 +1258,10 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
* In the case of ovl_adaptor sub driver, it needs to use the
* dma_dev_get function to get representative dma dev.
*/
- mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv->ddp_comp[path[0]]);
+ priv = priv->all_drm_private[path[0].sys];
+ mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv->ddp_comp[path[0].comp_id]);
+ mtk_crtc->vdisp_ao_dev = priv->vdisp_ao_dev;
ret = mtk_crtc_init(drm_dev, mtk_crtc, crtc_i);
if (ret < 0)
return ret;
@@ -1061,7 +1274,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
i = priv->mbox_index++;
- mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev;
+ mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev[priv->data->mmsys_id];
mtk_crtc->cmdq_client.client.tx_block = false;
mtk_crtc->cmdq_client.client.knows_txdone = true;
mtk_crtc->cmdq_client.client.rx_callback = ddp_cmdq_cb;
@@ -1101,6 +1314,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
#endif
if (conn_routes) {
+ priv = priv->all_drm_private[conn_mmsys];
for (i = 0; i < num_conn_routes; i++) {
unsigned int comp_id = conn_routes[i].route_ddp;
struct device_node *node = priv->comp_node[comp_id];
@@ -1117,6 +1331,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
mtk_ddp_comp_encoder_index_set(&priv->ddp_comp[comp_id]);
}
+ mtk_crtc->conn_routes_sys = conn_mmsys;
mtk_crtc->num_conn_routes = num_conn_routes;
mtk_crtc->conn_routes = conn_routes;
@@ -1124,5 +1339,10 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
mtk_crtc->ddp_comp_nr++;
}
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i])
+ device_link_add(mtk_crtc->base.dev->dev,
+ priv->all_drm_private[i]->mutex_dev, 0);
+
return 0;
}
@@ -15,10 +15,8 @@
#define MTK_MIN_BPC 3
void mtk_crtc_commit(struct drm_crtc *crtc);
-int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
- unsigned int path_len, int priv_data_index,
- const struct mtk_drm_route *conn_routes,
- unsigned int num_conn_routes);
+int mtk_crtc_create(struct drm_device *drm_dev,
+ enum mtk_crtc_path path_sel);
int mtk_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
struct mtk_plane_state *state);
void mtk_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane,
@@ -464,6 +464,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
[MTK_DISP_PWM] = "pwm",
[MTK_DISP_RDMA] = "rdma",
[MTK_DISP_UFOE] = "ufoe",
+ [MTK_DISP_VIRTUAL] = "virtual",
[MTK_DISP_WDMA] = "wdma",
[MTK_DP_INTF] = "dp-intf",
[MTK_DPI] = "dpi",
@@ -487,6 +488,15 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
[DDP_COMPONENT_COLOR0] = { MTK_DISP_COLOR, 0, &ddp_color },
[DDP_COMPONENT_COLOR1] = { MTK_DISP_COLOR, 1, &ddp_color },
[DDP_COMPONENT_DITHER0] = { MTK_DISP_DITHER, 0, &ddp_dither },
+ [DDP_COMPONENT_DLI_ASYNC0] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLI_ASYNC1] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLI_ASYNC8] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLI_ASYNC21] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLI_ASYNC22] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLI_ASYNC23] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLO_ASYNC1] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLO_ASYNC2] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLO_ASYNC3] = { MTK_DISP_VIRTUAL, -1, NULL },
[DDP_COMPONENT_DP_INTF0] = { MTK_DP_INTF, 0, &ddp_dpi },
[DDP_COMPONENT_DP_INTF1] = { MTK_DP_INTF, 1, &ddp_dpi },
[DDP_COMPONENT_DPI0] = { MTK_DPI, 0, &ddp_dpi },
@@ -494,6 +504,9 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
[DDP_COMPONENT_DRM_OVL_ADAPTOR] = { MTK_DISP_OVL_ADAPTOR, 0, &ddp_ovl_adaptor },
[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0] = { MTK_DISP_OVLSYS_ADAPTOR, 0, &ddp_ovlsys_adaptor},
[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1] = { MTK_DISP_OVLSYS_ADAPTOR, 1, &ddp_ovlsys_adaptor},
+ [DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0] = { MTK_DISP_OVLSYS_ADAPTOR, 0, &ddp_ovlsys_adaptor},
+ [DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1] = { MTK_DISP_OVLSYS_ADAPTOR, 1, &ddp_ovlsys_adaptor},
+ [DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2] = { MTK_DISP_OVLSYS_ADAPTOR, 2, &ddp_ovlsys_adaptor},
[DDP_COMPONENT_DSC0] = { MTK_DISP_DSC, 0, &ddp_dsc },
[DDP_COMPONENT_DSC1] = { MTK_DISP_DSC, 1, &ddp_dsc },
[DDP_COMPONENT_DSI0] = { MTK_DSI, 0, &ddp_dsi },
@@ -510,7 +523,10 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
[DDP_COMPONENT_OD0] = { MTK_DISP_OD, 0, &ddp_od },
[DDP_COMPONENT_OD1] = { MTK_DISP_OD, 1, &ddp_od },
[DDP_COMPONENT_OVL0] = { MTK_DISP_OVL, 0, &ddp_ovl },
+ [DDP_COMPONENT_OVL0_DLO_ASYNC5] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_OVL0_DLO_ASYNC6] = { MTK_DISP_VIRTUAL, -1, NULL },
[DDP_COMPONENT_OVL1] = { MTK_DISP_OVL, 1, &ddp_ovl },
+ [DDP_COMPONENT_OVL1_DLO_ASYNC5] = { MTK_DISP_VIRTUAL, -1, NULL },
[DDP_COMPONENT_OVL_2L0] = { MTK_DISP_OVL_2L, 0, &ddp_ovl },
[DDP_COMPONENT_OVL_2L1] = { MTK_DISP_OVL_2L, 1, &ddp_ovl },
[DDP_COMPONENT_OVL_2L2] = { MTK_DISP_OVL_2L, 2, &ddp_ovl },
@@ -567,12 +583,19 @@ static bool mtk_ddp_path_available(const unsigned int *path,
{
unsigned int i;
+ if (!path_len)
+ return true;
+
if (!path || !path_len)
return false;
for (i = 0U; i < path_len; i++) {
/* OVL_ADAPTOR doesn't have a device node */
- if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR)
+ if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR ||
+ path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 ||
+ path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 ||
+ path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 ||
+ mtk_ddp_comp_get_type(path[i]) == MTK_DISP_VIRTUAL)
continue;
if (!comp_node[path[i]])
@@ -597,44 +620,81 @@ int mtk_ddp_comp_get_id(struct device_node *node,
return -EINVAL;
}
+enum mtk_ddp_comp_type mtk_ddp_comp_get_type(unsigned int comp_id)
+{
+ return mtk_ddp_matches[comp_id].type;
+}
+
int mtk_find_possible_crtcs(struct drm_device *drm, struct device *dev)
{
struct mtk_drm_private *private = drm->dev_private;
const struct mtk_mmsys_driver_data *data;
struct mtk_drm_private *priv_n;
- int i = 0, j;
int ret;
+ int i = 0, j, count = 0;
+ bool found = false;
for (j = 0; j < private->data->mmsys_dev_num; j++) {
priv_n = private->all_drm_private[j];
data = priv_n->data;
if (mtk_ddp_path_available(data->main_path, data->main_len,
- priv_n->comp_node)) {
- if (mtk_ddp_comp_find(dev, data->main_path,
- data->main_len,
- priv_n->ddp_comp))
- return BIT(i);
- i++;
- }
+ priv_n->comp_node))
+ count++;
+
+ if (mtk_ddp_comp_find(dev, data->main_path, data->main_len,
+ priv_n->ddp_comp))
+ found = true;
+ }
+
+ if (count == private->data->mmsys_dev_num) {
+ if (found)
+ return BIT(i);
+ i++;
+ }
+
+ count = 0;
+ found = false;
+
+ for (j = 0; j < private->data->mmsys_dev_num; j++) {
+ priv_n = private->all_drm_private[j];
+ data = priv_n->data;
if (mtk_ddp_path_available(data->ext_path, data->ext_len,
- priv_n->comp_node)) {
- if (mtk_ddp_comp_find(dev, data->ext_path,
- data->ext_len,
- priv_n->ddp_comp))
- return BIT(i);
- i++;
- }
+ priv_n->comp_node))
+ count++;
+
+ if (mtk_ddp_comp_find(dev, data->ext_path, data->ext_len,
+ priv_n->ddp_comp))
+ found = true;
+ }
+
+ if (count == private->data->mmsys_dev_num) {
+ if (found)
+ return BIT(i);
+ i++;
+ }
+
+ count = 0;
+ found = false;
+
+ for (j = 0; j < private->data->mmsys_dev_num; j++) {
+ priv_n = private->all_drm_private[j];
+ data = priv_n->data;
if (mtk_ddp_path_available(data->third_path, data->third_len,
- priv_n->comp_node)) {
- if (mtk_ddp_comp_find(dev, data->third_path,
- data->third_len,
- priv_n->ddp_comp))
- return BIT(i);
- i++;
- }
+ priv_n->comp_node))
+ count++;
+
+ if (mtk_ddp_comp_find(dev, data->third_path, data->third_len,
+ priv_n->ddp_comp))
+ found = true;
+ }
+
+ if (count == private->data->mmsys_dev_num) {
+ if (found)
+ return BIT(i);
+ i++;
}
ret = mtk_ddp_comp_find_in_route(dev,
@@ -40,6 +40,7 @@ enum mtk_ddp_comp_type {
MTK_DISP_PWM,
MTK_DISP_RDMA,
MTK_DISP_UFOE,
+ MTK_DISP_VIRTUAL,
MTK_DISP_WDMA,
MTK_DPI,
MTK_DP_INTF,
@@ -47,6 +48,7 @@ enum mtk_ddp_comp_type {
MTK_OVL_BLENDER,
MTK_OVL_EXDMA,
MTK_OVL_OUTPROC,
+ MTK_VDISP_AO,
MTK_DDP_COMP_TYPE_MAX,
};
@@ -193,6 +193,10 @@ static const struct mtk_drm_route mt8188_mtk_ddp_main_routes[] = {
{0, DDP_COMPONENT_DSI0},
};
+static const struct mtk_drm_route mt8196_mtk_ddp_routes[] = {
+ {2, DDP_COMPONENT_DSI0},
+};
+
static const unsigned int mt8192_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0,
DDP_COMPONENT_OVL_2L0,
@@ -231,6 +235,50 @@ static const unsigned int mt8195_mtk_ddp_ext[] = {
DDP_COMPONENT_DP_INTF1,
};
+static const unsigned int mt8196_mtk_ddp_ovl0_main[] = {
+ DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0,
+ DDP_COMPONENT_OVL0_DLO_ASYNC5,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp0_main[] = {
+ DDP_COMPONENT_DLI_ASYNC0,
+ DDP_COMPONENT_DLO_ASYNC1,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp1_main[] = {
+ DDP_COMPONENT_DLI_ASYNC21,
+ DDP_COMPONENT_DVO0,
+};
+
+static const unsigned int mt8196_mtk_ddp_ovl0_ext[] = {
+ DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1,
+ DDP_COMPONENT_OVL0_DLO_ASYNC6,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp0_ext[] = {
+ DDP_COMPONENT_DLI_ASYNC1,
+ DDP_COMPONENT_DLO_ASYNC2,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp1_ext[] = {
+ DDP_COMPONENT_DLI_ASYNC22,
+ DDP_COMPONENT_DP_INTF0,
+};
+
+static const unsigned int mt8196_mtk_ddp_ovl1_third[] = {
+ DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2,
+ DDP_COMPONENT_OVL1_DLO_ASYNC5,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp0_third[] = {
+ DDP_COMPONENT_DLI_ASYNC8,
+ DDP_COMPONENT_DLO_ASYNC3,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp1_third[] = {
+ DDP_COMPONENT_DLI_ASYNC23,
+};
+
static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
.main_path = mt2701_mtk_ddp_main,
.main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
@@ -327,6 +375,67 @@ static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
.min_height = 1,
};
+static const struct mtk_mmsys_driver_data mt8196_dispsys0_driver_data = {
+ .main_path = mt8196_mtk_ddp_disp0_main,
+ .main_len = ARRAY_SIZE(mt8196_mtk_ddp_disp0_main),
+ .main_order = 1,
+ .ext_path = mt8196_mtk_ddp_disp0_ext,
+ .ext_len = ARRAY_SIZE(mt8196_mtk_ddp_disp0_ext),
+ .ext_order = 1,
+ .third_path = mt8196_mtk_ddp_disp0_third,
+ .third_len = ARRAY_SIZE(mt8196_mtk_ddp_disp0_third),
+ .third_order = 1,
+ .mmsys_id = DISPSYS0,
+ .mmsys_dev_num = 4,
+ .max_width = 8191,
+ .min_width = 2, /* 2-pixel align when ethdr is bypassed */
+ .min_height = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_dispsys1_driver_data = {
+ .main_path = mt8196_mtk_ddp_disp1_main,
+ .main_len = ARRAY_SIZE(mt8196_mtk_ddp_disp1_main),
+ .main_order = 2,
+ .ext_path = mt8196_mtk_ddp_disp1_ext,
+ .ext_len = ARRAY_SIZE(mt8196_mtk_ddp_disp1_ext),
+ .ext_order = 2,
+ .third_path = mt8196_mtk_ddp_disp1_third,
+ .third_len = ARRAY_SIZE(mt8196_mtk_ddp_disp1_third),
+ .conn_routes = mt8196_mtk_ddp_routes,
+ .num_conn_routes = ARRAY_SIZE(mt8196_mtk_ddp_routes),
+ .third_order = 2,
+ .mmsys_id = DISPSYS1,
+ .mmsys_dev_num = 4,
+ .max_width = 8191,
+ .min_width = 2, /* 2-pixel align when ethdr is bypassed */
+ .min_height = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_ovlsys0_driver_data = {
+ .main_path = mt8196_mtk_ddp_ovl0_main,
+ .main_len = ARRAY_SIZE(mt8196_mtk_ddp_ovl0_main),
+ .main_order = 0,
+ .ext_path = mt8196_mtk_ddp_ovl0_ext,
+ .ext_len = ARRAY_SIZE(mt8196_mtk_ddp_ovl0_ext),
+ .ext_order = 0,
+ .mmsys_id = OVLSYS0,
+ .mmsys_dev_num = 4,
+ .max_width = 8191,
+ .min_width = 2, /* 2-pixel align when ethdr is bypassed */
+ .min_height = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_ovlsys1_driver_data = {
+ .third_path = mt8196_mtk_ddp_ovl1_third,
+ .third_len = ARRAY_SIZE(mt8196_mtk_ddp_ovl1_third),
+ .third_order = 0,
+ .mmsys_id = OVLSYS1,
+ .mmsys_dev_num = 4,
+ .max_width = 8191,
+ .min_width = 2, /* 2-pixel align when ethdr is bypassed */
+ .min_height = 1,
+};
+
static const struct of_device_id mtk_drm_of_ids[] = {
{ .compatible = "mediatek,mt2701-mmsys",
.data = &mt2701_mmsys_driver_data},
@@ -354,6 +463,14 @@ static const struct of_device_id mtk_drm_of_ids[] = {
.data = &mt8195_vdosys0_driver_data},
{ .compatible = "mediatek,mt8195-vdosys1",
.data = &mt8195_vdosys1_driver_data},
+ { .compatible = "mediatek,mt8196-dispsys0",
+ .data = &mt8196_dispsys0_driver_data},
+ { .compatible = "mediatek,mt8196-dispsys1",
+ .data = &mt8196_dispsys1_driver_data},
+ { .compatible = "mediatek,mt8196-ovlsys0",
+ .data = &mt8196_ovlsys0_driver_data},
+ { .compatible = "mediatek,mt8196-ovlsys1",
+ .data = &mt8196_ovlsys1_driver_data},
{ }
};
MODULE_DEVICE_TABLE(of, mtk_drm_of_ids);
@@ -368,7 +485,7 @@ static int mtk_drm_match(struct device *dev, const void *data)
static bool mtk_drm_get_all_drm_priv(struct device *dev)
{
struct mtk_drm_private *drm_priv = dev_get_drvdata(dev);
- struct mtk_drm_private *all_drm_priv[MAX_CRTC];
+ struct mtk_drm_private *all_drm_priv[MAX_MMSYS] = {NULL};
struct mtk_drm_private *temp_drm_priv;
struct device_node *phandle = dev->parent->of_node;
const struct of_device_id *of_id;
@@ -395,23 +512,18 @@ static bool mtk_drm_get_all_drm_priv(struct device *dev)
if (!temp_drm_priv)
continue;
- if (temp_drm_priv->data->main_len)
- all_drm_priv[CRTC_MAIN] = temp_drm_priv;
- else if (temp_drm_priv->data->ext_len)
- all_drm_priv[CRTC_EXT] = temp_drm_priv;
- else if (temp_drm_priv->data->third_len)
- all_drm_priv[CRTC_THIRD] = temp_drm_priv;
+ all_drm_priv[temp_drm_priv->data->mmsys_id] = temp_drm_priv;
if (temp_drm_priv->mtk_drm_bound)
cnt++;
- if (cnt == MAX_CRTC)
+ if (cnt == temp_drm_priv->data->mmsys_dev_num)
break;
}
if (drm_priv->data->mmsys_dev_num == cnt) {
- for (i = 0; i < cnt; i++)
- for (j = 0; j < cnt; j++)
+ for (i = 0; i < MAX_MMSYS; i++)
+ for (j = 0; j < MAX_MMSYS; j++)
all_drm_priv[j]->all_drm_private[i] = all_drm_priv[i];
return true;
@@ -498,7 +610,10 @@ static int mtk_drm_kms_init(struct drm_device *drm)
drm->mode_config.funcs = &mtk_drm_mode_config_funcs;
drm->mode_config.helper_private = &mtk_drm_mode_config_helpers;
- for (i = 0; i < private->data->mmsys_dev_num; i++) {
+ for (i = 0; i < MAX_MMSYS; i++) {
+ if (!private->all_drm_private[i])
+ continue;
+
drm->dev_private = private->all_drm_private[i];
ret = component_bind_all(private->all_drm_private[i]->dev, drm);
if (ret)
@@ -521,8 +636,10 @@ static int mtk_drm_kms_init(struct drm_device *drm)
* third path.
*/
for (i = 0; i < MAX_CRTC; i++) {
- for (j = 0; j < private->data->mmsys_dev_num; j++) {
+ for (j = 0; j < MAX_MMSYS; j++) {
priv_n = private->all_drm_private[j];
+ if (!priv_n)
+ continue;
if (priv_n->data->max_width)
drm->mode_config.max_width = priv_n->data->max_width;
@@ -534,28 +651,23 @@ static int mtk_drm_kms_init(struct drm_device *drm)
drm->mode_config.min_height = priv_n->data->min_height;
if (i == CRTC_MAIN && priv_n->data->main_len) {
- ret = mtk_crtc_create(drm, priv_n->data->main_path,
- priv_n->data->main_len, j,
- priv_n->data->conn_routes,
- priv_n->data->num_conn_routes);
+ ret = mtk_crtc_create(drm, CRTC_MAIN);
if (ret)
goto err_component_unbind;
- continue;
+ break;
} else if (i == CRTC_EXT && priv_n->data->ext_len) {
- ret = mtk_crtc_create(drm, priv_n->data->ext_path,
- priv_n->data->ext_len, j, NULL, 0);
+ ret = mtk_crtc_create(drm, CRTC_EXT);
if (ret)
goto err_component_unbind;
- continue;
+ break;
} else if (i == CRTC_THIRD && priv_n->data->third_len) {
- ret = mtk_crtc_create(drm, priv_n->data->third_path,
- priv_n->data->third_len, j, NULL, 0);
+ ret = mtk_crtc_create(drm, CRTC_THIRD);
if (ret)
goto err_component_unbind;
- continue;
+ break;
}
}
}
@@ -574,8 +686,9 @@ static int mtk_drm_kms_init(struct drm_device *drm)
goto err_component_unbind;
}
- for (i = 0; i < private->data->mmsys_dev_num; i++)
- private->all_drm_private[i]->dma_dev = dma_dev;
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (private->all_drm_private[i])
+ private->all_drm_private[i]->dma_dev = dma_dev;
/*
* Configure the DMA segment size to make sure we get contiguous IOVA
@@ -593,11 +706,13 @@ static int mtk_drm_kms_init(struct drm_device *drm)
return 0;
err_component_unbind:
- for (i = 0; i < private->data->mmsys_dev_num; i++)
- component_unbind_all(private->all_drm_private[i]->dev, drm);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (private->all_drm_private[i])
+ component_unbind_all(private->all_drm_private[i]->dev, drm);
put_mutex_dev:
- for (i = 0; i < private->data->mmsys_dev_num; i++)
- put_device(private->all_drm_private[i]->mutex_dev);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (private->all_drm_private[i])
+ put_device(private->all_drm_private[i]->mutex_dev);
return ret;
}
@@ -661,6 +776,19 @@ static int mtk_drm_bind(struct device *dev)
}
private->mutex_dev = &pdev->dev;
+
+ if (private->vdisp_ao_node) {
+ pdev = of_find_device_by_node(private->vdisp_ao_node);
+ if (!pdev) {
+ dev_err(dev, "Waiting for vdisp_ao device %pOF\n",
+ private->vdisp_ao_node);
+ of_node_put(private->mutex_node);
+ of_node_put(private->vdisp_ao_node);
+ return -EPROBE_DEFER;
+ }
+ private->vdisp_ao_dev = &pdev->dev;
+ }
+
private->mtk_drm_bound = true;
private->dev = dev;
@@ -673,8 +801,9 @@ static int mtk_drm_bind(struct device *dev)
private->drm_master = true;
drm->dev_private = private;
- for (i = 0; i < private->data->mmsys_dev_num; i++)
- private->all_drm_private[i]->drm = drm;
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (private->all_drm_private[i])
+ private->all_drm_private[i]->drm = drm;
ret = mtk_drm_kms_init(drm);
if (ret < 0)
@@ -771,6 +900,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
.data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt8195-disp-mutex",
.data = (void *)MTK_DISP_MUTEX },
+ { .compatible = "mediatek,mt8196-disp-mutex",
+ .data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt8173-disp-od",
.data = (void *)MTK_DISP_OD },
{ .compatible = "mediatek,mt2701-disp-ovl",
@@ -837,6 +968,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
.data = (void *)MTK_DSI },
{ .compatible = "mediatek,mt8188-dsi",
.data = (void *)MTK_DSI },
+ { .compatible = "mediatek,mt8196-vdisp-ao",
+ .data = (void *)MTK_VDISP_AO },
{ }
};
@@ -1111,7 +1244,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
private->data = mtk_drm_data;
};
- private->all_drm_private = devm_kmalloc_array(dev, private->data->mmsys_dev_num,
+ private->all_drm_private = devm_kmalloc_array(dev, MAX_MMSYS,
sizeof(*private->all_drm_private),
GFP_KERNEL);
if (!private->all_drm_private)
@@ -1163,6 +1296,22 @@ static int mtk_drm_probe(struct platform_device *pdev)
component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
}
+ if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2)) {
+ struct mtk_drm_ovlsys_private ovlsys_priv;
+
+ ovlsys_priv.mmsys_dev = private->mmsys_dev;
+ ovlsys_priv.use_path =
+ mtk_drm_mmsys_comp_in_path(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2);
+ ovl_adaptor = platform_device_register_data(dev, "mediatek-disp-ovlsys-adaptor",
+ PLATFORM_DEVID_AUTO,
+ (void *)&ovlsys_priv,
+ sizeof(struct mtk_drm_ovlsys_private));
+ private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2].dev = &ovl_adaptor->dev;
+ mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2],
+ DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2);
+ component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
+ }
+
/* Iterate over sibling DISP function blocks */
for_each_child_of_node(phandle->parent, node) {
enum mtk_ddp_comp_type comp_type;
@@ -1189,6 +1338,12 @@ static int mtk_drm_probe(struct platform_device *pdev)
continue;
}
+ if (comp_type == MTK_VDISP_AO) {
+ private->vdisp_ao_node = of_node_get(node);
+ dev_dbg(dev, "get vdisp_ao node");
+ continue;
+ }
+
comp_id = mtk_ddp_comp_get_id(node, comp_type);
if (comp_id < 0) {
dev_warn(dev, "Skipping unknown component %pOF\n",
@@ -1241,6 +1396,9 @@ static int mtk_drm_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, private);
+ if (!match)
+ drm_of_component_match_add(dev, &match, component_compare_of, NULL);
+
ret = component_master_add_with_match(dev, &mtk_drm_ops, match);
if (ret)
goto err_pm;
@@ -1264,6 +1422,7 @@ static void mtk_drm_remove(struct platform_device *pdev)
component_master_del(&pdev->dev, &mtk_drm_ops);
pm_runtime_disable(&pdev->dev);
of_node_put(private->mutex_node);
+ of_node_put(private->vdisp_ao_node);
for (i = 0; i < DDP_COMPONENT_DRM_ID_MAX; i++)
of_node_put(private->comp_node[i]);
}
@@ -13,7 +13,8 @@
#define DDP_COMPONENT_DRM_OVL_ADAPTOR (DDP_COMPONENT_ID_MAX + 1)
#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1)
#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 + 1)
-#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 + 1)
+#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 + 1)
+#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 + 1)
enum mtk_crtc_path {
CRTC_MAIN,
@@ -22,6 +23,14 @@ enum mtk_crtc_path {
MAX_CRTC,
};
+enum mtk_drm_mmsys {
+ DISPSYS0,
+ DISPSYS1,
+ OVLSYS0,
+ OVLSYS1,
+ MAX_MMSYS,
+};
+
struct device;
struct device_node;
struct drm_crtc;
@@ -38,10 +47,13 @@ struct mtk_drm_route {
struct mtk_mmsys_driver_data {
const unsigned int *main_path;
unsigned int main_len;
+ unsigned int main_order;
const unsigned int *ext_path;
unsigned int ext_len;
+ unsigned int ext_order;
const unsigned int *third_path;
unsigned int third_len;
+ unsigned int third_order;
const struct mtk_drm_route *conn_routes;
unsigned int num_conn_routes;
@@ -63,6 +75,8 @@ struct mtk_drm_private {
struct device_node *mutex_node;
struct device *mutex_dev;
struct device *mmsys_dev;
+ struct device_node *vdisp_ao_node;
+ struct device *vdisp_ao_dev;
struct device_node *comp_node[DDP_COMPONENT_DRM_ID_MAX];
struct mtk_ddp_comp ddp_comp[DDP_COMPONENT_DRM_ID_MAX];
struct mtk_mmsys_driver_data *data;