Commit 8aa3dc3c authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm/panel/for-3.19-rc1' of git://people.freedesktop.org/~tagr/linux into drm-next

drm/panel: Changes for v3.19-rc1

This contains support for a couple of new panels, updates for some GPIO
API changes and a bunch of updates to the MIPI DSI support that should
make it easier to write panel drivers in the future.

* tag 'drm/panel/for-3.19-rc1' of git://people.freedesktop.org/~tagr/linux: (31 commits)
  drm/panel: Add Sharp LQ101R1SX01 support
  drm/dsi: Do not require .owner field to be set
  drm/dsi: Resolve MIPI DSI device from phandle
  drm/dsi: Implement DCS set_{column,page}_address commands
  drm/dsi: Implement DCS {get,set}_pixel_format commands
  drm/dsi: Implement DCS get_power_mode command
  drm/dsi: Implement DCS soft_reset command
  drm/dsi: Implement DCS nop command
  drm/dsi: Add to DocBook documentation
  drm/dsi: Implement some standard DCS commands
  drm/dsi: Implement generic read and write commands
  drm/panel: s6e8aa0: Use standard MIPI DSI function
  drm/dsi: Add mipi_dsi_set_maximum_return_packet_size() helper
  drm/dsi: Constify mipi_dsi_msg
  drm/dsi: Make mipi_dsi_dcs_{read,write}() symmetrical
  drm/dsi: Add DSI transfer helper
  drm/dsi: Add message to packet translator
  drm/dsi: Introduce packet format helpers
  drm/panel: s6e8aa0: Fix build warnings on 64-bit
  drm/panel: ld9040: Fix build warnings on 64-bit
  ...
parents fd172d0c 1976dbca
......@@ -2366,6 +2366,12 @@ void intel_crt_init(struct drm_device *dev)
!Pdrivers/gpu/drm/drm_dp_mst_topology.c dp mst helper
!Iinclude/drm/drm_dp_mst_helper.h
!Edrivers/gpu/drm/drm_dp_mst_topology.c
</sect2>
<sect2>
<title>MIPI DSI Helper Functions Reference</title>
!Pdrivers/gpu/drm/drm_mipi_dsi.c dsi helpers
!Iinclude/drm/drm_mipi_dsi.h
!Edrivers/gpu/drm/drm_mipi_dsi.c
</sect2>
<sect2>
<title>EDID Helper Functions Reference</title>
......
AU Optronics Corporation 11.6" HD (1366x768) color TFT-LCD panel
Required properties:
- compatible: should be "auo,b116xw03"
This binding is compatible with the simple-panel binding, which is specified
in simple-panel.txt in this directory.
HannStar Display Corp. HSD070PWW1 7.0" WXGA TFT LCD panel
Required properties:
- compatible: should be "hannstar,hsd070pww1"
This binding is compatible with the simple-panel binding, which is specified
in simple-panel.txt in this directory.
Hitachi Ltd. Corporation 9" WVGA (800x480) TFT LCD panel
Required properties:
- compatible: should be "hit,tx23d38vm0caa"
This binding is compatible with the simple-panel binding, which is specified
in simple-panel.txt in this directory.
Innolux Corporation 12.1" WXGA (1280x800) TFT LCD panel
Required properties:
- compatible: should be "innolux,g121i1-l01"
This binding is compatible with the simple-panel binding, which is specified
in simple-panel.txt in this directory.
Sharp Microelectronics 10.1" WQXGA TFT LCD panel
This panel requires a dual-channel DSI host to operate. It supports two modes:
- left-right: each channel drives the left or right half of the screen
- even-odd: each channel drives the even or odd lines of the screen
Each of the DSI channels controls a separate DSI peripheral. The peripheral
driven by the first link (DSI-LINK1), left or even, is considered the primary
peripheral and controls the device. The 'link2' property contains a phandle
to the peripheral driven by the second link (DSI-LINK2, right or odd).
Note that in video mode the DSI-LINK1 interface always provides the left/even
pixels and DSI-LINK2 always provides the right/odd pixels. In command mode it
is possible to program either link to drive the left/even or right/odd pixels
but for the sake of consistency this binding assumes that the same assignment
is chosen as for video mode.
Required properties:
- compatible: should be "sharp,lq101r1sx01"
- reg: DSI virtual channel of the peripheral
Required properties (for DSI-LINK1 only):
- link2: phandle to the DSI peripheral on the secondary link. Note that the
presence of this property marks the containing node as DSI-LINK1.
- power-supply: phandle of the regulator that provides the supply voltage
Optional properties (for DSI-LINK1 only):
- backlight: phandle of the backlight device attached to the panel
Example:
dsi@54300000 {
panel: panel@0 {
compatible = "sharp,lq101r1sx01";
reg = <0>;
link2 = <&secondary>;
power-supply = <...>;
backlight = <...>;
};
};
dsi@54400000 {
secondary: panel@0 {
compatible = "sharp,lq101r1sx01";
reg = <0>;
};
};
......@@ -64,8 +64,10 @@ gmt Global Mixed-mode Technology, Inc.
google Google, Inc.
gumstix Gumstix, Inc.
gw Gateworks Corporation
hannstar HannStar Display Corporation
haoyu Haoyu Microelectronic Co. Ltd.
hisilicon Hisilicon Limited.
hit Hitachi Ltd.
honeywell Honeywell
hp Hewlett Packard
i2se I2SE GmbH
......
This diff is collapsed.
......@@ -1236,7 +1236,7 @@ static bool exynos_dsi_is_short_dsi_type(u8 type)
}
static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host,
struct mipi_dsi_msg *msg)
const struct mipi_dsi_msg *msg)
{
struct exynos_dsi *dsi = host_to_dsi(host);
struct exynos_dsi_transfer xfer;
......
......@@ -27,4 +27,17 @@ config DRM_PANEL_S6E8AA0
select DRM_MIPI_DSI
select VIDEOMODE_HELPERS
config DRM_PANEL_SHARP_LQ101R1SX01
tristate "Sharp LQ101R1SX01 panel"
depends on OF
depends on DRM_MIPI_DSI
help
Say Y here if you want to enable support for Sharp LQ101R1SX01
TFT-LCD modules. The panel has a 2560x1600 resolution and uses
24 bit RGB per pixel. It provides a dual MIPI DSI interface to
the host and has a built-in LED backlight.
To compile this driver as a module, choose M here: the module
will be called panel-sharp-lq101r1sx01.
endmenu
obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
obj-$(CONFIG_DRM_PANEL_LD9040) += panel-ld9040.o
obj-$(CONFIG_DRM_PANEL_S6E8AA0) += panel-s6e8aa0.o
obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o
......@@ -145,7 +145,7 @@ static void ld9040_dcs_write(struct ld9040 *ctx, const u8 *data, size_t len)
if (ctx->error < 0 || len == 0)
return;
dev_dbg(ctx->dev, "writing dcs seq: %*ph\n", len, data);
dev_dbg(ctx->dev, "writing dcs seq: %*ph\n", (int)len, data);
ret = ld9040_spi_write_word(ctx, *data);
while (!ret && --len) {
......@@ -154,8 +154,8 @@ static void ld9040_dcs_write(struct ld9040 *ctx, const u8 *data, size_t len)
}
if (ret) {
dev_err(ctx->dev, "error %d writing dcs seq: %*ph\n", ret, len,
data);
dev_err(ctx->dev, "error %d writing dcs seq: %*ph\n", ret,
(int)len, data);
ctx->error = ret;
}
......@@ -336,17 +336,12 @@ static int ld9040_probe(struct spi_device *spi)
if (ret < 0)
return ret;
ctx->reset_gpio = devm_gpiod_get(dev, "reset");
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ctx->reset_gpio)) {
dev_err(dev, "cannot get reset-gpios %ld\n",
PTR_ERR(ctx->reset_gpio));
return PTR_ERR(ctx->reset_gpio);
}
ret = gpiod_direction_output(ctx->reset_gpio, 1);
if (ret < 0) {
dev_err(dev, "cannot configure reset-gpios %d\n", ret);
return ret;
}
spi->bits_per_word = 9;
ret = spi_setup(spi);
......
......@@ -141,10 +141,10 @@ static void s6e8aa0_dcs_write(struct s6e8aa0 *ctx, const void *data, size_t len)
if (ctx->error < 0)
return;
ret = mipi_dsi_dcs_write(dsi, data, len);
ret = mipi_dsi_dcs_write_buffer(dsi, data, len);
if (ret < 0) {
dev_err(ctx->dev, "error %zd writing dcs seq: %*ph\n", ret, len,
data);
dev_err(ctx->dev, "error %zd writing dcs seq: %*ph\n", ret,
(int)len, data);
ctx->error = ret;
}
}
......@@ -800,27 +800,15 @@ static void s6e8aa0_panel_init(struct s6e8aa0 *ctx)
}
static void s6e8aa0_set_maximum_return_packet_size(struct s6e8aa0 *ctx,
int size)
u16 size)
{
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
const struct mipi_dsi_host_ops *ops = dsi->host->ops;
u8 buf[] = {size, 0};
struct mipi_dsi_msg msg = {
.channel = dsi->channel,
.type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
.tx_len = sizeof(buf),
.tx_buf = buf
};
int ret;
if (ctx->error < 0)
return;
if (!ops || !ops->transfer)
ret = -EIO;
else
ret = ops->transfer(dsi->host, &msg);
ret = mipi_dsi_set_maximum_return_packet_size(dsi, size);
if (ret < 0) {
dev_err(ctx->dev,
"error %d setting maximum return packet size to %d\n",
......@@ -1019,17 +1007,12 @@ static int s6e8aa0_probe(struct mipi_dsi_device *dsi)
return ret;
}
ctx->reset_gpio = devm_gpiod_get(dev, "reset");
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ctx->reset_gpio)) {
dev_err(dev, "cannot get reset-gpios %ld\n",
PTR_ERR(ctx->reset_gpio));
return PTR_ERR(ctx->reset_gpio);
}
ret = gpiod_direction_output(ctx->reset_gpio, 1);
if (ret < 0) {
dev_err(dev, "cannot configure reset-gpios %d\n", ret);
return ret;
}
ctx->brightness = GAMMA_LEVEL_NUM - 1;
......@@ -1069,7 +1052,6 @@ static struct mipi_dsi_driver s6e8aa0_driver = {
.remove = s6e8aa0_remove,
.driver = {
.name = "panel_s6e8aa0",
.owner = THIS_MODULE,
.of_match_table = s6e8aa0_of_match,
},
};
......
This diff is collapsed.
......@@ -247,21 +247,14 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
if (IS_ERR(panel->supply))
return PTR_ERR(panel->supply);
panel->enable_gpio = devm_gpiod_get_optional(dev, "enable");
panel->enable_gpio = devm_gpiod_get_optional(dev, "enable",
GPIOD_OUT_LOW);
if (IS_ERR(panel->enable_gpio)) {
err = PTR_ERR(panel->enable_gpio);
dev_err(dev, "failed to request GPIO: %d\n", err);
return err;
}
if (panel->enable_gpio) {
err = gpiod_direction_output(panel->enable_gpio, 0);
if (err < 0) {
dev_err(dev, "failed to setup GPIO: %d\n", err);
return err;
}
}
backlight = of_parse_phandle(dev->of_node, "backlight", 0);
if (backlight) {
panel->backlight = of_find_backlight_by_node(backlight);
......@@ -376,6 +369,29 @@ static const struct panel_desc auo_b101xtn01 = {
},
};
static const struct drm_display_mode auo_b116xw03_mode = {
.clock = 70589,
.hdisplay = 1366,
.hsync_start = 1366 + 40,
.hsync_end = 1366 + 40 + 40,
.htotal = 1366 + 40 + 40 + 32,
.vdisplay = 768,
.vsync_start = 768 + 10,
.vsync_end = 768 + 10 + 12,
.vtotal = 768 + 10 + 12 + 6,
.vrefresh = 60,
};
static const struct panel_desc auo_b116xw03 = {
.modes = &auo_b116xw03_mode,
.num_modes = 1,
.bpc = 6,
.size = {
.width = 256,
.height = 144,
},
};
static const struct drm_display_mode auo_b133xtn01_mode = {
.clock = 69500,
.hdisplay = 1366,
......@@ -415,6 +431,7 @@ static const struct drm_display_mode auo_b133htn01_mode = {
static const struct panel_desc auo_b133htn01 = {
.modes = &auo_b133htn01_mode,
.num_modes = 1,
.bpc = 6,
.size = {
.width = 293,
.height = 165,
......@@ -536,22 +553,92 @@ static const struct drm_display_mode foxlink_fl500wvr00_a0t_mode = {
static const struct panel_desc foxlink_fl500wvr00_a0t = {
.modes = &foxlink_fl500wvr00_a0t_mode,
.num_modes = 1,
.bpc = 8,
.size = {
.width = 108,
.height = 65,
},
};
static const struct drm_display_mode innolux_n116bge_mode = {
static const struct drm_display_mode hannstar_hsd070pww1_mode = {
.clock = 71100,
.hdisplay = 1280,
.hsync_start = 1280 + 1,
.hsync_end = 1280 + 1 + 158,
.htotal = 1280 + 1 + 158 + 1,
.vdisplay = 800,
.vsync_start = 800 + 1,
.vsync_end = 800 + 1 + 21,
.vtotal = 800 + 1 + 21 + 1,
.vrefresh = 60,
};
static const struct panel_desc hannstar_hsd070pww1 = {
.modes = &hannstar_hsd070pww1_mode,
.num_modes = 1,
.bpc = 6,
.size = {
.width = 151,
.height = 94,
},
};
static const struct drm_display_mode hitachi_tx23d38vm0caa_mode = {
.clock = 33333,
.hdisplay = 800,
.hsync_start = 800 + 85,
.hsync_end = 800 + 85 + 86,
.htotal = 800 + 85 + 86 + 85,
.vdisplay = 480,
.vsync_start = 480 + 16,
.vsync_end = 480 + 16 + 13,
.vtotal = 480 + 16 + 13 + 16,
.vrefresh = 60,
};
static const struct panel_desc hitachi_tx23d38vm0caa = {
.modes = &hitachi_tx23d38vm0caa_mode,
.num_modes = 1,
.bpc = 6,
.size = {
.width = 195,
.height = 117,
},
};
static const struct drm_display_mode innolux_g121i1_l01_mode = {
.clock = 71000,
.hdisplay = 1280,
.hsync_start = 1280 + 64,
.hsync_end = 1280 + 64 + 32,
.htotal = 1280 + 64 + 32 + 64,
.vdisplay = 800,
.vsync_start = 800 + 9,
.vsync_end = 800 + 9 + 6,
.vtotal = 800 + 9 + 6 + 9,
.vrefresh = 60,
};
static const struct panel_desc innolux_g121i1_l01 = {
.modes = &innolux_g121i1_l01_mode,
.num_modes = 1,
.bpc = 6,
.size = {
.width = 261,
.height = 163,
},
};
static const struct drm_display_mode innolux_n116bge_mode = {
.clock = 76420,
.hdisplay = 1366,
.hsync_start = 1366 + 64,
.hsync_end = 1366 + 64 + 6,
.htotal = 1366 + 64 + 6 + 64,
.hsync_start = 1366 + 136,
.hsync_end = 1366 + 136 + 30,
.htotal = 1366 + 136 + 30 + 60,
.vdisplay = 768,
.vsync_start = 768 + 8,
.vsync_end = 768 + 8 + 4,
.vtotal = 768 + 8 + 4 + 8,
.vsync_end = 768 + 8 + 12,
.vtotal = 768 + 8 + 12 + 12,
.vrefresh = 60,
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
};
......@@ -642,6 +729,9 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "auo,b101xtn01",
.data = &auo_b101xtn01,
}, {
.compatible = "auo,b116xw03",
.data = &auo_b116xw03,
}, {
.compatible = "auo,b133htn01",
.data = &auo_b133htn01,
......@@ -666,6 +756,15 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "foxlink,fl500wvr00-a0t",
.data = &foxlink_fl500wvr00_a0t,
}, {
.compatible = "hannstar,hsd070pww1",
.data = &hannstar_hsd070pww1,
}, {
.compatible = "hit,tx23d38vm0caa",
.data = &hitachi_tx23d38vm0caa
}, {
.compatible ="innolux,g121i1-l01",
.data = &innolux_g121i1_l01
}, {
.compatible = "innolux,n116bge",
.data = &innolux_n116bge,
......@@ -741,6 +840,7 @@ static const struct panel_desc_dsi lg_ld070wx3_sl01 = {
.desc = {
.modes = &lg_ld070wx3_sl01_mode,
.num_modes = 1,
.bpc = 8,
.size = {
.width = 94,
.height = 151,
......@@ -768,6 +868,7 @@ static const struct panel_desc_dsi lg_lh500wx1_sd03 = {
.desc = {
.modes = &lg_lh500wx1_sd03_mode,
.num_modes = 1,
.bpc = 8,
.size = {
.width = 62,
.height = 110,
......@@ -795,6 +896,7 @@ static const struct panel_desc_dsi panasonic_vvx10f004b00 = {
.desc = {
.modes = &panasonic_vvx10f004b00_mode,
.num_modes = 1,
.bpc = 8,
.size = {
.width = 217,
.height = 136,
......@@ -864,7 +966,6 @@ static void panel_simple_dsi_shutdown(struct mipi_dsi_device *dsi)
static struct mipi_dsi_driver panel_simple_dsi_driver = {
.driver = {
.name = "panel-simple-dsi",
.owner = THIS_MODULE,
.of_match_table = dsi_of_match,
},
.probe = panel_simple_dsi_probe,
......
......@@ -26,6 +26,7 @@ struct mipi_dsi_device;
* struct mipi_dsi_msg - read/write DSI buffer
* @channel: virtual channel id
* @type: payload data type
* @flags: flags controlling this message transmission
* @tx_len: length of @tx_buf
* @tx_buf: data to be written
* @rx_len: length of @rx_buf
......@@ -43,12 +44,44 @@ struct mipi_dsi_msg {
void *rx_buf;
};
bool mipi_dsi_packet_format_is_short(u8 type);
bool mipi_dsi_packet_format_is_long(u8 type);
/**
* struct mipi_dsi_packet - represents a MIPI DSI packet in protocol format
* @size: size (in bytes) of the packet
* @header: the four bytes that make up the header (Data ID, Word Count or
* Packet Data, and ECC)
* @payload_length: number of bytes in the payload
* @payload: a pointer to a buffer containing the payload, if any
*/
struct mipi_dsi_packet {
size_t size;
u8 header[4];
size_t payload_length;
const u8 *payload;
};
int mipi_dsi_create_packet(struct mipi_dsi_packet *packet,
const struct mipi_dsi_msg *msg);
/**
* struct mipi_dsi_host_ops - DSI bus operations
* @attach: attach DSI device to DSI host
* @detach: detach DSI device from DSI host
* @transfer: send and/or receive DSI packet, return number of received bytes,
* or error
* @transfer: transmit a DSI packet
*
* DSI packets transmitted by .transfer() are passed in as mipi_dsi_msg
* structures. This structure contains information about the type of packet
* being transmitted as well as the transmit and receive buffers. When an
* error is encountered during transmission, this function will return a
* negative error code. On success it shall return the number of bytes
* transmitted for write packets or the number of bytes received for read
* packets.
*
* Note that typically DSI packet transmission is atomic, so the .transfer()
* function will seldomly return anything other than the number of bytes
* contained in the transmit buffer on success.
*/
struct mipi_dsi_host_ops {
int (*attach)(struct mipi_dsi_host *host,
......@@ -56,7 +89,7 @@ struct mipi_dsi_host_ops {
int (*detach)(struct mipi_dsi_host *host,
struct mipi_dsi_device *dsi);
ssize_t (*transfer)(struct mipi_dsi_host *host,
struct mipi_dsi_msg *msg);
const struct mipi_dsi_msg *msg);
};
/**
......@@ -130,12 +163,57 @@ static inline struct mipi_dsi_device *to_mipi_dsi_device(struct device *dev)
return container_of(dev, struct mipi_dsi_device, dev);
}
struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np);
int mipi_dsi_attach(struct mipi_dsi_device *dsi);
int mipi_dsi_detach(struct mipi_dsi_device *dsi);
ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, const void *data,
size_t len);
int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
u16 value);
ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
size_t size);
ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
size_t num_params, void *data, size_t size);
/**
* enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
* @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking
* information only
* @MIPI_DSI_DCS_TEAR_MODE_VHBLANK : the TE output line consists of both
* V-Blanking and H-Blanking information
*/
enum mipi_dsi_dcs_tear_mode {
MIPI_DSI_DCS_TEAR_MODE_VBLANK,
MIPI_DSI_DCS_TEAR_MODE_VHBLANK,
};
#define MIPI_DSI_DCS_POWER_MODE_DISPLAY (1 << 2)
#define MIPI_DSI_DCS_POWER_MODE_NORMAL (1 << 3)
#define MIPI_DSI_DCS_POWER_MODE_SLEEP (1 << 4)
#define MIPI_DSI_DCS_POWER_MODE_PARTIAL (1 << 5)
#define MIPI_DSI_DCS_POWER_MODE_IDLE (1 << 6)
ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
const void *data, size_t len);
ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
const void *data, size_t len);
ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
size_t len);
int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode);
int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format);
int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start,
u16 end);
int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start,
u16 end);
int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
enum mipi_dsi_dcs_tear_mode mode);
int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format);
/**
* struct mipi_dsi_driver - DSI driver
......@@ -167,9 +245,13 @@ static inline void mipi_dsi_set_drvdata(struct mipi_dsi_device *dsi, void *data)
dev_set_drvdata(&dsi->dev, data);
}
int mipi_dsi_driver_register(struct mipi_dsi_driver *driver);
int mipi_dsi_driver_register_full(struct mipi_dsi_driver *driver,
struct module *owner);
void mipi_dsi_driver_unregister(struct mipi_dsi_driver *driver);
#define mipi_dsi_driver_register(driver) \
mipi_dsi_driver_register_full(driver, THIS_MODULE)
#define module_mipi_dsi_driver(__mipi_dsi_driver) \
module_driver(__mipi_dsi_driver, mipi_dsi_driver_register, \
mipi_dsi_driver_unregister)
......
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