Skip to content

Commit

Permalink
Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
klogg committed Sep 11, 2024
1 parent 5644d7d commit 1ded38d
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 109 deletions.
5 changes: 1 addition & 4 deletions bridge/it66121_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -898,10 +898,7 @@ static int __init it66121_probe(void)
return 0;
}

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

static struct i2c_driver it66121_driver = {
Expand Down
5 changes: 3 additions & 2 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 @@ -103,7 +104,7 @@ 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);
unsigned int width, unsigned int pitch);
int fl2000_streaming_enable(struct usb_device *usb_dev);
void fl2000_streaming_disable(struct usb_device *usb_dev);

Expand Down Expand Up @@ -138,6 +139,6 @@ 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);
bool fl2000_drm_vblank(struct usb_device *usb_dev);
void fl2000_drm_vblank(struct usb_device *usb_dev);

#endif /* __FL2000_DRM_H__ */
107 changes: 78 additions & 29 deletions fl2000_drm.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ static const u32 fl2000_pixel_formats[] = {
DRM_FORMAT_XRGB8888,
};

/* IT66121 HDMI bridge driver name*/
static const char *const fl2000_supported_bridge = "it66121";
/* TODO: This has to come from driver parameters */
static char *fl2000_supported_bridge = "it66121";

/* Maximum pixel clock set to 500MHz. It is hard to get more or less precise PLL configuration for
* higher clock
Expand Down Expand Up @@ -93,6 +93,7 @@ struct fl2000_drm_if {
struct drm_device drm;
struct drm_simple_display_pipe pipe;
struct usb_device *usb_dev;
bool vblank_enabled;
};

DEFINE_DRM_GEM_DMA_FOPS(fl2000_drm_driver_fops);
Expand Down Expand Up @@ -340,6 +341,26 @@ static void fl2000_display_update(struct drm_simple_display_pipe *pipe,
}
}

static int fl2000_display_enable_vblank(struct drm_simple_display_pipe *pipe)
{
struct drm_crtc *crtc = &pipe->crtc;
struct drm_device *drm = crtc->dev;
struct fl2000_drm_if *drm_if = container_of(drm, struct fl2000_drm_if, drm);

drm_if->vblank_enabled = true;

return 0;
}

static void fl2000_display_disable_vblank(struct drm_simple_display_pipe *pipe)
{
struct drm_crtc *crtc = &pipe->crtc;
struct drm_device *drm = crtc->dev;
struct fl2000_drm_if *drm_if = container_of(drm, struct fl2000_drm_if, drm);

drm_if->vblank_enabled = false;
}

/* Logical pipe management (no HW configuration here) */
static const struct drm_simple_display_pipe_funcs fl2000_display_funcs = {
.mode_valid = fl2000_display_mode_valid,
Expand Down Expand Up @@ -420,25 +441,32 @@ void fl2000_drm_hotplug(struct usb_device *usb_dev)
return;
}

drm_kms_helper_hotplug_event(drm_if->drm);
drm_kms_helper_hotplug_event(&drm_if->drm);
}

bool fl2000_drm_vblank(struct usb_device *usb_dev)
void fl2000_drm_vblank(struct usb_device *usb_dev)
{
int ret;
struct fl2000_drm_if *drm_if;
struct drm_crtc *crtc;

drm_if = dev_get_drvdata(&usb_dev->dev);
if (!drm_if) {
dev_err(&usb_dev->dev, "Cannot find DRM structure!");
return false;
return;
}

drm_crtc_handle_vblank(drm_if->crtc);
if (!drm_if->vblank_enabled)
return;

crtc = &drm_if->pipe.crtc;
ret = drm_crtc_handle_vblank(crtc);
if (ret)
dev_err(&usb_dev->dev, "Cannot handle vblank event (%d)", ret);
}

static int fl2000_drm_modeset_init(struct drm_device *drm)
{

return 0;
}

Expand All @@ -452,13 +480,20 @@ static int fl2000_drm_bind(struct device *master)

dev_info(master, "Binding FL2000 master");

drm_if = dev_get_drvdata(&usb_dev->dev);
if (!drm_if) {
dev_err(&usb_dev->dev, "Cannot find DRM structure!");
return -ENODEV;
}

/* Attach bridge */
ret = component_bind_all(master, &drm_if->pipe);
if (ret) {
dev_err(&usb_dev->dev, "Cannot attach bridge (%d)", ret);
return ret;
}

drm = &drm_if->drm;
drm_mode_config_reset(drm);

fl2000_reset(usb_dev);
Expand All @@ -481,11 +516,18 @@ static void fl2000_drm_unbind(struct device *master)
{
/* It is assumed that master is FL2000 USB device */
struct usb_device *usb_dev = to_usb_device(master);
struct fl2000_drm_if *drm_if = res;
struct drm_device *drm = &drm_if->drm;
struct fl2000_drm_if *drm_if;
struct drm_device *drm;

dev_info(master, "Unbinding FL2000 master");

drm_if = dev_get_drvdata(&usb_dev->dev);
if (!drm_if) {
dev_err(&usb_dev->dev, "Cannot find DRM structure!");
return;
}

drm = &drm_if->drm;
drm_atomic_helper_shutdown(drm);

/* Detach bridge */
Expand All @@ -502,26 +544,25 @@ static struct component_master_ops fl2000_master_ops = {
/**
* Will only allocate structures on 'probe' function call. There is still no bridge at this moment,
* so registration of the device and modesetting does not make any sense.
*
*
* We do not configure DMA mask here because we link DRM device to the USB device provided.
* We also do not set up polling because connect/disconnect events are provided in interrupts.
*
* @param interface USB interface to attach DRM device to
*
* @param usb_dev USB device structure
*
* @return 0 on success, negative value on error
*/
int fl2000_drm_init(struct usb_interface *interface)
int fl2000_drm_init(struct usb_device *usb_dev)
{
int ret;
struct fl2000_drm_if *drm_if;
struct drm_device *drm;
struct drm_mode_config *mode_config;
struct component_match *match = NULL;
struct usb_device *usb_dev = interface_to_usbdev(interface);

/* DRM device is allocated together with private data structure and attached to the device */
drm_if = devm_drm_dev_alloc(&usb_dev->dev, &fl2000_drm_driver, struct fl2000_drm_if, drm);
if (IS_ERR(drm_if)) {
dev_err(&interface->dev, "Cannot allocate DRM structure (%ld)", PTR_ERR(drm_if));
dev_err(&usb_dev->dev, "Cannot allocate DRM structure (%ld)", PTR_ERR(drm_if));
return (int)PTR_ERR(drm_if);
}
drm = &drm_if->drm;
Expand All @@ -530,7 +571,7 @@ int fl2000_drm_init(struct usb_interface *interface)
/* Static mode configuration that won't change */
ret = drmm_mode_config_init(drm);
if (ret) {
dev_err(&interface->dev, "Cannot initialize DRM mode (%d)", ret);
dev_err(&usb_dev->dev, "Cannot initialize DRM mode (%d)", ret);
drm_dev_put(drm);
return ret;
}
Expand All @@ -546,7 +587,7 @@ int fl2000_drm_init(struct usb_interface *interface)
fl2000_pixel_formats, ARRAY_SIZE(fl2000_pixel_formats),
NULL, NULL);
if (ret) {
dev_err(&interface->dev, "Cannot configure simple display pipe (%d)", ret);
dev_err(&usb_dev->dev, "Cannot configure simple display pipe (%d)", ret);
drm_mode_config_cleanup(drm);
drm_dev_put(drm);
return ret;
Expand All @@ -555,7 +596,8 @@ int fl2000_drm_init(struct usb_interface *interface)
/* We support vblanks */
ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
if (ret) {
dev_err(&interface->dev, "Failed to initialize %d vblank(s) (%d)", drm->mode_config.num_crtc, ret);
dev_err(&usb_dev->dev, "Failed to initialize %d vblank(s) (%d)",
drm->mode_config.num_crtc, ret);
drm_mode_config_cleanup(drm);
drm_dev_put(drm);
return ret;
Expand All @@ -565,20 +607,20 @@ int fl2000_drm_init(struct usb_interface *interface)
drm_encoder_helper_add(&drm_if->pipe.encoder, &fl2000_encoder_funcs);

/* Register supported HDMI bridge as a component with match by name */
ret = component_match_add(&usb_dev->dev, &match, component_compare_dev_name, fl2000_supported_bridge);
if (ret) {
dev_err(&interface->dev, "Cannot add component match! (%d)", ret);
component_match_add(&usb_dev->dev, &match, component_compare_dev_name,
fl2000_supported_bridge);
if (!match) {
dev_err(&usb_dev->dev, "Cannot find supported HDMI bridge!");
drm_mode_config_cleanup(drm);
drm_dev_put(drm);
return ret;
return -ENODEV;
}

/* Register component master - component bind/unbind functions will complete the registration
* and initializtion of DRM device chain
/* Register component master - component bind/unbind functions will complete the
* registration and initializtion of DRM device chain
*/
ret = component_master_add_with_match(&usb_dev->dev, &fl2000_master_ops, match);
if (ret) {
dev_err(&interface->dev, "Cannot register component master (%d)", ret);
dev_err(&usb_dev->dev, "Cannot register component master (%d)", ret);
drm_mode_config_cleanup(drm);
drm_dev_put(drm);
return ret;
Expand All @@ -589,13 +631,20 @@ int fl2000_drm_init(struct usb_interface *interface)
return 0;
}

void fl2000_drm_cleanup(struct usb_interface *interface)
void fl2000_drm_cleanup(struct usb_device *usb_dev)
{
struct usb_device *usb_dev = interface_to_usbdev(interface);
struct drm_device *drm;
struct fl2000_drm_if *drm_if = dev_get_drvdata(&usb_dev->dev);

if (!drm_if) {
dev_err(&usb_dev->dev, "Cannot find DRM structure!");
return;
}

dev_set_drvdata(&usb_dev->dev, NULL);
component_master_del(&usb_dev->dev, &fl2000_master_ops);

drm = &drm_if->drm;
drm_mode_config_cleanup(drm);
drm_dev_put(drm);
}
35 changes: 19 additions & 16 deletions fl2000_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,29 @@

#define USB_DRIVER_NAME "fl2000_usb"

#define USB_VENDOR_FRESCO_LOGIC 0x1D5C
#define USB_PRODUCT_FL2000 0x2000
#define FL2000_USB_VENDOR 0x1D5C
#define FL2000_USB_PRODUCT 0x2000
#define FL2000_USB_INTERFACE(ifnum, api_addr) \
{ \
USB_DEVICE_INTERFACE_NUMBER(FL2000_USB_VENDOR, FL2000_USB_PRODUCT, ifnum), \
.driver_info = (kernel_ulong_t)(api_addr) \
}

struct fl2000_if_api
{
int(*create)(struct usb_interface *interface);
void(*destroy)(struct usb_interface *interface);
struct fl2000_if_api {
int (*create)(struct usb_interface *interface);
void (*destroy)(struct usb_interface *interface);
};

static int fl2000_avcontrol_create(struct usb_interface *interface)
{

struct usb_device *usb_dev = interface_to_usbdev(interface);
struct component_match *match = NULL;
int ret;

/* This seem to be needed to workaround buggy implementation of EPs */
ret = usb_set_interface(usb_dev, FL2000_USBIF_AVCONTROL, 1);
if (ret) {
dev_err(&interface->dev, "Cannot set streaming interface for bulk transfers (%d)", ret);
dev_err(&interface->dev, "Cannot set streaming interface for bulk transfers (%d)",
ret);
return ret;
}

Expand Down Expand Up @@ -80,9 +83,9 @@ static const struct fl2000_if_api fl2000_interrupt = {
};

static const struct usb_device_id fl2000_id_table[] = {
{ USB_DEVICE_INTERFACE_NUMBER(USB_VENDOR_FRESCO_LOGIC, USB_PRODUCT_FL2000, FL2000_USBIF_AVCONTROL), .driver_info = &fl2000_avcontrol },
{ USB_DEVICE_INTERFACE_NUMBER(USB_VENDOR_FRESCO_LOGIC, USB_PRODUCT_FL2000, FL2000_USBIF_STREAMING), .driver_info = &fl2000_streaming },
{ USB_DEVICE_INTERFACE_NUMBER(USB_VENDOR_FRESCO_LOGIC, USB_PRODUCT_FL2000, FL2000_USBIF_INTERRUPT), .driver_info = &fl2000_interrupt },
FL2000_USB_INTERFACE(FL2000_USBIF_AVCONTROL, &fl2000_avcontrol),
FL2000_USB_INTERFACE(FL2000_USBIF_STREAMING, &fl2000_streaming),
FL2000_USB_INTERFACE(FL2000_USBIF_INTERRUPT, &fl2000_interrupt),
{},
};
MODULE_DEVICE_TABLE(usb, fl2000_id_table);
Expand All @@ -105,16 +108,16 @@ static int fl2000_probe(struct usb_interface *interface, const struct usb_device

static void fl2000_disconnect(struct usb_interface *interface)
{
const struct usb_device_id *usb_match_id;;
const struct usb_device_id *id;
const struct fl2000_if_api *api;

usb_match_id = usb_match_id(interface, fl2000_id_table);
if (!usb_match_id) {
id = usb_match_id(interface, fl2000_id_table);
if (!id) {
dev_err(&interface->dev, "Cannot find matching USB ID");
return;
}

api = (const struct fl2000_if_api *)usb_match_id->driver_info;
api = (const struct fl2000_if_api *)id->driver_info;
if (api && api->destroy)
api->destroy(interface);
}
Expand Down
1 change: 0 additions & 1 deletion fl2000_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ int fl2000_i2c_init(struct usb_device *usb_dev)
{
int ret;
struct i2c_adapter *adapter;
u8 usb_path[32];

/* Adapter must be allocated before anything else */
adapter = devres_alloc(fl2000_i2c_adapter_release, sizeof(*adapter), GFP_KERNEL);
Expand Down
Loading

0 comments on commit 1ded38d

Please sign in to comment.