Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
0004  */
0005 
0006 #include <drm/drm_edid.h>
0007 
0008 #include "dpu_writeback.h"
0009 
0010 static int dpu_wb_conn_get_modes(struct drm_connector *connector)
0011 {
0012     struct drm_device *dev = connector->dev;
0013     struct msm_drm_private *priv = dev->dev_private;
0014     struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
0015 
0016     /*
0017      * We should ideally be limiting the modes only to the maxlinewidth but
0018      * on some chipsets this will allow even 4k modes to be added which will
0019      * fail the per SSPP bandwidth checks. So, till we have dual-SSPP support
0020      * and source split support added lets limit the modes based on max_mixer_width
0021      * as 4K modes can then be supported.
0022      */
0023     return drm_add_modes_noedid(connector, dpu_kms->catalog->caps->max_mixer_width,
0024             dev->mode_config.max_height);
0025 }
0026 
0027 static const struct drm_connector_funcs dpu_wb_conn_funcs = {
0028     .reset = drm_atomic_helper_connector_reset,
0029     .fill_modes = drm_helper_probe_single_connector_modes,
0030     .destroy = drm_connector_cleanup,
0031     .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
0032     .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
0033 };
0034 
0035 static int dpu_wb_conn_prepare_job(struct drm_writeback_connector *connector,
0036         struct drm_writeback_job *job)
0037 {
0038 
0039     struct dpu_wb_connector *dpu_wb_conn = to_dpu_wb_conn(connector);
0040 
0041     if (!job->fb)
0042         return 0;
0043 
0044     dpu_encoder_prepare_wb_job(dpu_wb_conn->wb_enc, job);
0045 
0046     return 0;
0047 }
0048 
0049 static void dpu_wb_conn_cleanup_job(struct drm_writeback_connector *connector,
0050         struct drm_writeback_job *job)
0051 {
0052     struct dpu_wb_connector *dpu_wb_conn = to_dpu_wb_conn(connector);
0053 
0054     if (!job->fb)
0055         return;
0056 
0057     dpu_encoder_cleanup_wb_job(dpu_wb_conn->wb_enc, job);
0058 }
0059 
0060 static const struct drm_connector_helper_funcs dpu_wb_conn_helper_funcs = {
0061     .get_modes = dpu_wb_conn_get_modes,
0062     .prepare_writeback_job = dpu_wb_conn_prepare_job,
0063     .cleanup_writeback_job = dpu_wb_conn_cleanup_job,
0064 };
0065 
0066 int dpu_writeback_init(struct drm_device *dev, struct drm_encoder *enc,
0067         const u32 *format_list, u32 num_formats)
0068 {
0069     struct dpu_wb_connector *dpu_wb_conn;
0070     int rc = 0;
0071 
0072     dpu_wb_conn = devm_kzalloc(dev->dev, sizeof(*dpu_wb_conn), GFP_KERNEL);
0073 
0074     drm_connector_helper_add(&dpu_wb_conn->base.base, &dpu_wb_conn_helper_funcs);
0075 
0076     /* DPU initializes the encoder and sets it up completely for writeback
0077      * cases and hence should use the new API drm_writeback_connector_init_with_encoder
0078      * to initialize the writeback connector
0079      */
0080     rc = drm_writeback_connector_init_with_encoder(dev, &dpu_wb_conn->base, enc,
0081             &dpu_wb_conn_funcs, format_list, num_formats);
0082 
0083     if (!rc)
0084         dpu_wb_conn->wb_enc = enc;
0085 
0086     return rc;
0087 }