@@ -19,6 +19,7 @@
*/
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_dp_helper.h>
#include <linux/module.h>
#include <linux/seq_file.h>
@@ -27,6 +28,7 @@
#include <linux/debugfs.h>
#include <linux/fb.h>
+#include <linux/i2c.h>
#include <linux/pci.h>
#include <linux/console.h>
#include <linux/vga_switcheroo.h>
@@ -37,6 +39,8 @@
struct vga_switcheroo_client {
struct pci_dev *pdev;
struct fb_info *fb_info;
+ struct i2c_adapter *ddc;
+ struct drm_dp_aux *aux;
struct work_struct reprobe_work;
int pwr_state;
const struct vga_switcheroo_client_ops *ops;
@@ -355,6 +359,64 @@ out:
}
EXPORT_SYMBOL(vga_switcheroo_unlock_ddc);
+void vga_switcheroo_set_ddc(struct pci_dev *pdev, struct i2c_adapter *ddc)
+{
+ struct vga_switcheroo_client *client;
+
+ mutex_lock(&vgasr_mutex);
+ client = find_client_from_pci(&vgasr_priv.clients, pdev);
+ if (client)
+ client->ddc = ddc;
+ mutex_unlock(&vgasr_mutex);
+
+ /* DDC is stored after AUX on eDP, so we have both now */
+ if (client->active)
+ vga_switcheroo_reprobe_inactive_clients();
+}
+EXPORT_SYMBOL(vga_switcheroo_set_ddc);
+
+struct i2c_adapter *vga_switcheroo_get_ddc(struct pci_dev *pdev)
+{
+ struct vga_switcheroo_client *active = NULL;
+
+ mutex_lock(&vgasr_mutex);
+ if (find_client_from_pci(&vgasr_priv.clients, pdev))
+ active = find_active_client(&vgasr_priv.clients);
+ mutex_unlock(&vgasr_mutex);
+ if (!active)
+ return NULL;
+
+ return active->ddc;
+}
+EXPORT_SYMBOL(vga_switcheroo_get_ddc);
+
+void vga_switcheroo_set_aux(struct pci_dev *pdev, struct drm_dp_aux *aux)
+{
+ struct vga_switcheroo_client *client;
+
+ mutex_lock(&vgasr_mutex);
+ client = find_client_from_pci(&vgasr_priv.clients, pdev);
+ if (client)
+ client->aux = aux;
+ mutex_unlock(&vgasr_mutex);
+}
+EXPORT_SYMBOL(vga_switcheroo_set_aux);
+
+struct drm_dp_aux *vga_switcheroo_get_aux(struct pci_dev *pdev)
+{
+ struct vga_switcheroo_client *active = NULL;
+
+ mutex_lock(&vgasr_mutex);
+ if (find_client_from_pci(&vgasr_priv.clients, pdev))
+ active = find_active_client(&vgasr_priv.clients);
+ mutex_unlock(&vgasr_mutex);
+ if (!active || !active->ddc)
+ return NULL;
+
+ return active->aux;
+}
+EXPORT_SYMBOL(vga_switcheroo_get_aux);
+
static int vga_switcheroo_show(struct seq_file *m, void *v)
{
struct vga_switcheroo_client *client;
@@ -10,7 +10,10 @@
#ifndef _LINUX_VGA_SWITCHEROO_H_
#define _LINUX_VGA_SWITCHEROO_H_
+#include <drm/drm_dp_helper.h>
+
#include <linux/fb.h>
+#include <linux/i2c.h>
struct pci_dev;
@@ -56,6 +59,10 @@ void vga_switcheroo_client_fb_set(struct pci_dev *dev,
int vga_switcheroo_lock_ddc(struct pci_dev *pdev);
int vga_switcheroo_unlock_ddc(struct pci_dev *pdev);
+void vga_switcheroo_set_ddc(struct pci_dev *pdev, struct i2c_adapter *ddc);
+struct i2c_adapter *vga_switcheroo_get_ddc(struct pci_dev *pdev);
+void vga_switcheroo_set_aux(struct pci_dev *pdev, struct drm_dp_aux *aux);
+struct drm_dp_aux *vga_switcheroo_get_aux(struct pci_dev *pdev);
int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler);
void vga_switcheroo_unregister_handler(void);
@@ -77,6 +84,10 @@ static inline int vga_switcheroo_register_client(struct pci_dev *dev,
static inline void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info) {}
static inline int vga_switcheroo_lock_ddc(struct pci_dev *pdev) { return -ENODEV; }
static inline int vga_switcheroo_unlock_ddc(struct pci_dev *pdev) { return -ENODEV; }
+static inline void vga_switcheroo_set_ddc(struct pci_dev *pdev, struct i2c_adapter *ddc) {}
+static inline struct i2c_adapter *vga_switcheroo_get_ddc(struct pci_dev *pdev) { return NULL; }
+static inline void vga_switcheroo_set_aux(struct pci_dev *pdev, struct drm_dp_aux *aux) {}
+static inline struct drm_dp_aux *vga_switcheroo_get_aux(struct pci_dev *pdev) { return NULL; }
static inline int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) { return 0; }
static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
const struct vga_switcheroo_client_ops *ops,