linux/drivers/gpu/drm/loongson/lsdc_output_7a2000.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2023 Loongson Technology Corporation Limited
 */

#include <linux/delay.h>

#include <drm/drm_atomic_helper.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_edid.h>
#include <drm/drm_probe_helper.h>

#include "lsdc_drv.h"
#include "lsdc_output.h"

/*
 * The display controller in LS7A2000 has two display pipes
 * Display pipe 0 is attached with a built-in transparent VGA encoder and
 * a built-in HDMI encoder.
 * Display pipe 1 has only one built-in HDMI encoder connected.
 *       ______________________                          _____________
 *      |             +-----+  |                        |             |
 *      | CRTC0 -+--> | VGA |  ----> VGA Connector ---> | VGA Monitor |<---+
 *      |        |    +-----+  |                        |_____________|    |
 *      |        |             |                         ______________    |
 *      |        |    +------+ |                        |              |   |
 *      |        +--> | HDMI | ----> HDMI Connector --> | HDMI Monitor |<--+
 *      |             +------+ |                        |______________|   |
 *      |            +------+  |                                           |
 *      |            | i2c6 |  <-------------------------------------------+
 *      |            +------+  |
 *      |                      |
 *      |    DC in LS7A2000    |
 *      |                      |
 *      |            +------+  |
 *      |            | i2c7 |  <--------------------------------+
 *      |            +------+  |                                |
 *      |                      |                          ______|_______
 *      |            +------+  |                         |              |
 *      | CRTC1 ---> | HDMI |  ----> HDMI Connector ---> | HDMI Monitor |
 *      |            +------+  |                         |______________|
 *      |______________________|
 */

static int ls7a2000_connector_get_modes(struct drm_connector *connector)
{}

static struct drm_encoder *
ls7a2000_connector_get_best_encoder(struct drm_connector *connector,
				    struct drm_atomic_state *state)
{}

static const struct drm_connector_helper_funcs ls7a2000_connector_helpers =;

/* debugfs */

#define LSDC_HDMI_REG(i, reg)

static const struct lsdc_reg32 ls7a2000_hdmi0_encoder_regs[] =;

static const struct lsdc_reg32 ls7a2000_hdmi1_encoder_regs[] =;

static int ls7a2000_hdmi_encoder_regs_show(struct seq_file *m, void *data)
{}

static const struct drm_info_list ls7a2000_hdmi0_debugfs_files[] =;

static const struct drm_info_list ls7a2000_hdmi1_debugfs_files[] =;

static void ls7a2000_hdmi0_late_register(struct drm_connector *connector,
					 struct dentry *root)
{}

static void ls7a2000_hdmi1_late_register(struct drm_connector *connector,
					 struct dentry *root)
{}

/* monitor present detection */

static enum drm_connector_status
ls7a2000_hdmi0_vga_connector_detect(struct drm_connector *connector, bool force)
{}

static enum drm_connector_status
ls7a2000_hdmi1_connector_detect(struct drm_connector *connector, bool force)
{}

static const struct drm_connector_funcs ls7a2000_hdmi_connector_funcs[2] =;

/* Even though some board has only one hdmi on display pipe 1,
 * We still need hook lsdc_encoder_funcs up on display pipe 0,
 * This is because we need its reset() callback get called, to
 * set the LSDC_HDMIx_CTRL_REG using software gpio emulated i2c.
 * Otherwise, the firmware may set LSDC_HDMIx_CTRL_REG blindly.
 */
static void ls7a2000_hdmi0_encoder_reset(struct drm_encoder *encoder)
{}

static void ls7a2000_hdmi1_encoder_reset(struct drm_encoder *encoder)
{}

static const struct drm_encoder_funcs ls7a2000_encoder_funcs[2] =;

static int ls7a2000_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
					   struct drm_display_mode *mode)
{}

static void ls7a2000_hdmi_atomic_disable(struct drm_encoder *encoder,
					 struct drm_atomic_state *state)
{}

static void ls7a2000_hdmi_atomic_enable(struct drm_encoder *encoder,
					struct drm_atomic_state *state)
{}

/*
 *  Fout = M * Fin
 *
 *  M = (4 * LF) / (IDF * ODF)
 *
 *  IDF: Input Division Factor
 *  ODF: Output Division Factor
 *   LF: Loop Factor
 *    M: Required Mult
 *
 *  +--------------------------------------------------------+
 *  |     Fin (kHZ)     | M  | IDF | LF | ODF |   Fout(Mhz)  |
 *  |-------------------+----+-----+----+-----+--------------|
 *  |  170000 ~ 340000  | 10 | 16  | 40 |  1  | 1700 ~ 3400  |
 *  |   85000 ~ 170000  | 10 |  8  | 40 |  2  |  850 ~ 1700  |
 *  |   42500 ~  85000  | 10 |  4  | 40 |  4  |  425 ~ 850   |
 *  |   21250 ~  42500  | 10 |  2  | 40 |  8  | 212.5 ~ 425  |
 *  |   20000 ~  21250  | 10 |  1  | 40 | 16  |  200 ~ 212.5 |
 *  +--------------------------------------------------------+
 */
static void ls7a2000_hdmi_phy_pll_config(struct lsdc_device *ldev,
					 int fin,
					 unsigned int index)
{}

static void ls7a2000_hdmi_atomic_mode_set(struct drm_encoder *encoder,
					  struct drm_crtc_state *crtc_state,
					  struct drm_connector_state *conn_state)
{}

static const struct drm_encoder_helper_funcs ls7a2000_encoder_helper_funcs =;

/*
 * For LS7A2000:
 *
 * 1) Most of board export one vga + hdmi output interface.
 * 2) Yet, Some boards export double hdmi output interface.
 * 3) Still have boards export three output(2 hdmi + 1 vga).
 *
 * So let's hook hdmi helper funcs to all display pipe, don't miss.
 * writing hdmi register do no harms.
 */
int ls7a2000_output_init(struct drm_device *ddev,
			 struct lsdc_display_pipe *dispipe,
			 struct i2c_adapter *ddc,
			 unsigned int pipe)
{}