Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Structural adjustments #74

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 48 additions & 36 deletions bridge/it66121_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ static int it66121_configure_afe(struct it66121_priv *priv, int clock_khz)

static int it66121_wait_ddc_ready(struct it66121_priv *priv)
{
int ret, val;
int ret;
unsigned int val;

ret = regmap_field_read_poll_timeout(priv->ddc_done, val, true, EDID_SLEEP, EDID_TIMEOUT);
if (ret)
Expand Down Expand Up @@ -221,7 +222,7 @@ static int it66121_clear_ddc_fifo(struct it66121_priv *priv)

static int it66121_abort_ddc_ops(struct it66121_priv *priv)
{
int i, ret;
int ret;

/* Prior to DDC abort command there was also a reset of HDCP:
* 1. HDCP_DESIRE clear bit CP DESIRE
Expand All @@ -233,7 +234,7 @@ static int it66121_abort_ddc_ops(struct it66121_priv *priv)
/* From original driver: According to 2009/01/15 modification by [email protected]
* do abort DDC twice
*/
for (i = 0; i < 2; i++) {
for (int i = 0; i < 2; i++) {
ret = regmap_write(priv->regmap, IT66121_DDC_COMMAND, DDC_CMD_ABORT);
if (ret)
return ret;
Expand Down Expand Up @@ -326,9 +327,11 @@ static void it66121_intr_work(struct work_struct *work_item)

static int it66121_get_edid_block(void *context, u8 *buf, unsigned int block, size_t len)
{
int i, ret, offset = block & 1 ? 128 : 0;
int ret;
size_t remain = len;
unsigned int rd_fifo_val, segment = block >> 1;
unsigned int val;
unsigned int segment = block >> 1;
unsigned int offset = block & 1 ? 128 : 0;
static const u8 header[EDID_LOSS_LEN] = { 0x00, 0xFF, 0xFF };
struct it66121_priv *priv = context;

Expand All @@ -354,35 +357,36 @@ static int it66121_get_edid_block(void *context, u8 *buf, unsigned int block, si
/* Clear DDC FIFO */
ret = it66121_clear_ddc_fifo(priv);
if (ret)
break;
return ret;

ret = regmap_write(priv->regmap, IT66121_DDC_ADDRESS, EDID_DDC_ADDR);
if (ret)
break;
return ret;

/* Account 3 bytes that will be lost */
ret = regmap_write(priv->regmap, IT66121_DDC_OFFSET, offset - EDID_LOSS_LEN);
if (ret)
break;
return ret;

ret = regmap_write(priv->regmap, IT66121_DDC_SIZE, (unsigned int)size);
if (ret)
break;
return ret;
ret = regmap_write(priv->regmap, IT66121_DDC_SEGMENT, segment);
if (ret)
break;
return ret;
ret = regmap_write(priv->regmap, IT66121_DDC_COMMAND, DDC_CMD_EDID_READ);
if (ret)
break;
return ret;

/* Deduct lost bytes when reading from FIFO */
size -= EDID_LOSS_LEN;

for (i = 0; i < size; i++) {
ret = regmap_read(priv->regmap, IT66121_DDC_RD_FIFO, &rd_fifo_val);
for (int i = 0; i < size; i++) {
ret = regmap_read(priv->regmap, IT66121_DDC_RD_FIFO, &val);
if (ret)
return ret;

*(buf++) = rd_fifo_val & 0xFF;
*(buf++) = val & 0xFF;
}

remain -= size;
Expand Down Expand Up @@ -450,30 +454,27 @@ static int it66121_bind(struct device *comp, struct device *master, void *master
{
int ret;
struct drm_bridge *bridge = dev_get_drvdata(comp);
struct drm_simple_display_pipe *pipe = master_data;
struct i2c_adapter *adapter = i2c_verify_adapter(master);

if (!adapter)
return -ENODEV;
struct drm_device *drm = master_data;

dev_info(comp, "Binding IT66121 component");
dev_info(comp, "Binding IT66121 component to %s", dev_name(master));

/* XXX: check adapter, check bridge */

ret = drm_simple_display_pipe_attach_bridge(pipe, bridge);
if (ret)
dev_err(comp, "Cannot attach IT66121 bridge (%d)", ret);
/* TODO: change to devm/devres from master
* Or maybe use drv_data of some device other than usb_dev?
* Also this hast o be linked to some specific encoder
*/
drm->dev_private = bridge;

return ret;
}

static void it66121_unbind(struct device *comp, struct device *master, void *master_data)
{
/* TODO: drm_bridge_detach()? */
UNUSED(master);
UNUSED(master_data);
struct drm_bridge *bridge = dev_get_drvdata(comp);
struct drm_device *drm = master_data;

dev_info(comp, "Unbinding IT66121 component from %s", dev_name(master));

dev_info(comp, "Unbinding IT66121 component");
drm_bridge_detach(bridge);
}

static const struct component_ops it66121_component_ops = {
Expand Down Expand Up @@ -566,7 +567,7 @@ static int it66121_bridge_attach(struct drm_bridge *bridge, enum drm_bridge_atta

static void it66121_bridge_detach(struct drm_bridge *bridge)
{
/* TODO: Detach encoder */
/* TODO: Detach bridge poperly */
dev_info(bridge->dev->dev, "it66121_bridge_detach");
}

Expand Down Expand Up @@ -601,7 +602,7 @@ static void it66121_bridge_mode_set(struct drm_bridge *bridge, const struct drm_
const struct drm_display_mode *adjusted_mode)

{
int i, ret;
int ret;
ssize_t frame_size;
struct it66121_priv *priv = container_of(bridge, struct it66121_priv, bridge);
u8 buf[HDMI_INFOFRAME_SIZE(AVI)];
Expand Down Expand Up @@ -658,7 +659,7 @@ static void it66121_bridge_mode_set(struct drm_bridge *bridge, const struct drm_
}

/* Write new AVI infoframe packet */
for (i = 0; i < HDMI_AVI_INFOFRAME_SIZE; i++) {
for (int i = 0; i < HDMI_AVI_INFOFRAME_SIZE; i++) {
ret = regmap_write(priv->regmap, aviinfo_reg[i],
buf[i + HDMI_INFOFRAME_HEADER_SIZE]);
if (ret) {
Expand Down Expand Up @@ -764,7 +765,7 @@ static int it66121_regs_init(struct it66121_priv *priv, struct i2c_client *clien

static int it66121_i2c_probe(struct i2c_adapter *adapter, unsigned short address)
{
int i, ret;
int ret;
u8 id_regs[] = { IT66121_VENDOR_ID_1, IT66121_VENDOR_ID_2, IT66121_DEVICE_ID_1,
IT66121_DEVICE_ID_2 };
union {
Expand All @@ -784,7 +785,7 @@ static int it66121_i2c_probe(struct i2c_adapter *adapter, unsigned short address
return -ENODEV;
}

for (i = 0; i < ARRAY_SIZE(id_regs); i++) {
for (int i = 0; i < ARRAY_SIZE(id_regs); i++) {
struct i2c_msg msgs[] = {
{ .addr = address, .flags = 0, .len = 1, .buf = &id_regs[i] },
{ .addr = address, .flags = I2C_M_RD, .len = 1, .buf = &id.b[i] }
Expand Down Expand Up @@ -899,8 +900,19 @@ static int __init it66121_probe(void)
return 0;
}

module_init(it66121_probe);
module_exit(it66121_remove);
static const struct i2c_device_id it66121_ids[] = { { "it66121", 0 }, {} };
MODULE_DEVICE_TABLE(i2c, it66121_ids);

static struct i2c_driver it66121_driver = {
.probe = it66121_probe,
.remove = it66121_remove,
.driver = {
.name = "it66121",
},
.id_table = it66121_ids,
};

module_i2c_driver(it66121_driver);

MODULE_AUTHOR("Artem Mygaiev");
MODULE_DESCRIPTION("IT66121 HDMI transmitter driver");
Expand Down
105 changes: 35 additions & 70 deletions fl2000.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <drm/drm_probe_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_fb_dma_helper.h>
#include <drm/drm_fbdev_dma.h>

#include "fl2000_registers.h"

Expand Down Expand Up @@ -71,53 +72,6 @@ enum fl2000_interface {
(__mask) |= __data.__val; \
})

static inline int fl2000_submit_urb(struct urb *urb)
{
int ret;
int attempts = 10;

do {
ret = usb_submit_urb(urb, GFP_KERNEL);
switch (ret) {
case -ENXIO:
case -ENOMEM:
if (attempts--) {
cond_resched();
ret = -EAGAIN;
}
break;
default:
break;
}
} while (ret == -EAGAIN);

return ret;
}

static inline int fl2000_urb_status(struct usb_device *usb_dev, int status, int pipe)
{
int ret = status;

switch (status) {
/* Stalled endpoint */
case -EPIPE:
ret = usb_clear_halt(usb_dev, pipe);
break;
case -ECONNRESET:
fallthrough;
case -ENOENT:
fallthrough;
case -ESHUTDOWN:
/* Not an error */
break;
default:
dev_err(&usb_dev->dev, "Nonzero urb status, %d\n", status);
break;
}

return ret;
}

struct fl2000_timings {
u32 hactive;
u32 htotal;
Expand All @@ -137,33 +91,41 @@ struct fl2000_pll {
};

/* Timeout in us for I2C read/write operations */
#define I2C_RDWR_INTERVAL (200)
#define I2C_RDWR_INTERVAL 200
#define I2C_RDWR_TIMEOUT (256 * 1000)

/* Streaming transfer task */
struct fl2000_stream;
struct fl2000_stream *fl2000_stream_create(struct usb_device *usb_dev, struct drm_crtc *crtc);
void fl2000_stream_destroy(struct usb_device *usb_dev);

/* Streaming interface */
int fl2000_stream_mode_set(struct fl2000_stream *stream, int pixels, u32 bytes_pix);
void fl2000_stream_compress(struct fl2000_stream *stream, void *src, unsigned int height,
unsigned int width, unsigned int pitch);
int fl2000_stream_enable(struct fl2000_stream *stream);
void fl2000_stream_disable(struct fl2000_stream *stream);

/* Interrupt polling task */
struct fl2000_intr;
struct fl2000_intr *fl2000_intr_create(struct usb_device *usb_dev, struct drm_device *drm);
void fl2000_intr_destroy(struct usb_device *usb_dev);
/* Endpoints we want to use for Bulk streaming and Interrupt transfers */
#define STREAMING_EP 1
#define INTERRUPT_EP 3

/* Streaming transfer task creation */
int fl2000_streaming_create(struct usb_interface *interface);
void fl2000_streaming_destroy(struct usb_interface *interface);
/* ... and interface */
int fl2000_streaming_mode_set(struct usb_device *usb_dev, int pixels, u32 bytes_pix);
void fl2000_streaming_compress(struct usb_device *usb_dev, void *src, unsigned int height,
unsigned int width, unsigned int pitch);
int fl2000_streaming_enable(struct usb_device *usb_dev);
void fl2000_streaming_disable(struct usb_device *usb_dev);

/* Interrupt polling task creation */
int fl2000_interrupt_create(struct usb_interface *interface);
void fl2000_interrupt_destroy(struct usb_interface *interface);
/* ... and interface */
int fl2000_enable_interrupt(struct usb_device *usb_dev);
int fl2000_disable_interrupt(struct usb_device *usb_dev);

/* I2C adapter interface creation */
struct i2c_adapter *fl2000_i2c_init(struct usb_device *usb_dev);
int fl2000_i2c_init(struct usb_device *usb_dev);
void fl2000_i2c_cleanup(struct usb_device *usb_dev);
/* ... and interface*/
bool fl2000_i2c_verify_client(struct usb_device *usb_dev, struct device *client_dev,
const char *client_name);

/* Register map creation */
struct regmap *fl2000_regmap_init(struct usb_device *usb_dev);

/* Registers interface */
int fl2000_regmap_init(struct usb_device *usb_dev);
void fl2000_regmap_cleanup(struct usb_device *usb_dev);
/* ... and interface */
int fl2000_reset(struct usb_device *usb_dev);
int fl2000_usb_magic(struct usb_device *usb_dev);
int fl2000_afe_magic(struct usb_device *usb_dev);
Expand All @@ -176,7 +138,10 @@ int fl2000_check_interrupt(struct usb_device *usb_dev);
int fl2000_i2c_dword(struct usb_device *usb_dev, bool read, u16 addr, u8 offset, u32 *data);

/* DRM device creation */
int fl2000_drm_bind(struct device *master);
void fl2000_drm_unbind(struct device *master);
int fl2000_drm_init(struct usb_device *usb_dev);
void fl2000_drm_cleanup(struct usb_device *usb_dev);
/* ... and interface */
void fl2000_drm_hotplug(struct usb_device *usb_dev);
void fl2000_drm_vblank(struct usb_device *usb_dev);

#endif /* __FL2000_DRM_H__ */
Loading