Subversion Repositories Kolibri OS

Rev

Rev 5060 | Rev 6088 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright © 2009 Keith Packard
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided that
  6.  * the above copyright notice appear in all copies and that both that copyright
  7.  * notice and this permission notice appear in supporting documentation, and
  8.  * that the name of the copyright holders not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  The copyright holders make no representations
  11.  * about the suitability of this software for any purpose.  It is provided "as
  12.  * is" without express or implied warranty.
  13.  *
  14.  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16.  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  20.  * OF THIS SOFTWARE.
  21.  */
  22.  
  23. #include <linux/kernel.h>
  24. #include <linux/module.h>
  25. //#include <linux/delay.h>
  26. //#include <linux/init.h>
  27. #include <linux/errno.h>
  28. #include <linux/sched.h>
  29. #include <linux/i2c.h>
  30. #include <drm/drm_dp_helper.h>
  31. #include <drm/drmP.h>
  32.  
  33. /**
  34.  * DOC: dp helpers
  35.  *
  36.  * These functions contain some common logic and helpers at various abstraction
  37.  * levels to deal with Display Port sink devices and related things like DP aux
  38.  * channel transfers, EDID reading over DP aux channels, decoding certain DPCD
  39.  * blocks, ...
  40.  */
  41.  
  42. /* Helpers for DP link training */
  43. static u8 dp_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r)
  44. {
  45.         return link_status[r - DP_LANE0_1_STATUS];
  46. }
  47.  
  48. static u8 dp_get_lane_status(const u8 link_status[DP_LINK_STATUS_SIZE],
  49.                              int lane)
  50. {
  51.         int i = DP_LANE0_1_STATUS + (lane >> 1);
  52.         int s = (lane & 1) * 4;
  53.         u8 l = dp_link_status(link_status, i);
  54.         return (l >> s) & 0xf;
  55. }
  56.  
  57. bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE],
  58.                           int lane_count)
  59. {
  60.         u8 lane_align;
  61.         u8 lane_status;
  62.         int lane;
  63.  
  64.         lane_align = dp_link_status(link_status,
  65.                                     DP_LANE_ALIGN_STATUS_UPDATED);
  66.         if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
  67.                 return false;
  68.         for (lane = 0; lane < lane_count; lane++) {
  69.                 lane_status = dp_get_lane_status(link_status, lane);
  70.                 if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS)
  71.                         return false;
  72.         }
  73.         return true;
  74. }
  75. EXPORT_SYMBOL(drm_dp_channel_eq_ok);
  76.  
  77. bool drm_dp_clock_recovery_ok(const u8 link_status[DP_LINK_STATUS_SIZE],
  78.                               int lane_count)
  79. {
  80.         int lane;
  81.         u8 lane_status;
  82.  
  83.         for (lane = 0; lane < lane_count; lane++) {
  84.                 lane_status = dp_get_lane_status(link_status, lane);
  85.                 if ((lane_status & DP_LANE_CR_DONE) == 0)
  86.                         return false;
  87.         }
  88.         return true;
  89. }
  90. EXPORT_SYMBOL(drm_dp_clock_recovery_ok);
  91.  
  92. u8 drm_dp_get_adjust_request_voltage(const u8 link_status[DP_LINK_STATUS_SIZE],
  93.                                      int lane)
  94. {
  95.         int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
  96.         int s = ((lane & 1) ?
  97.                  DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
  98.                  DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
  99.         u8 l = dp_link_status(link_status, i);
  100.  
  101.         return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
  102. }
  103. EXPORT_SYMBOL(drm_dp_get_adjust_request_voltage);
  104.  
  105. u8 drm_dp_get_adjust_request_pre_emphasis(const u8 link_status[DP_LINK_STATUS_SIZE],
  106.                                           int lane)
  107. {
  108.         int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
  109.         int s = ((lane & 1) ?
  110.                  DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
  111.                  DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
  112.         u8 l = dp_link_status(link_status, i);
  113.  
  114.         return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
  115. }
  116. EXPORT_SYMBOL(drm_dp_get_adjust_request_pre_emphasis);
  117.  
  118. void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) {
  119.         if (dpcd[DP_TRAINING_AUX_RD_INTERVAL] == 0)
  120.                 udelay(100);
  121.         else
  122.                 mdelay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] * 4);
  123. }
  124. EXPORT_SYMBOL(drm_dp_link_train_clock_recovery_delay);
  125.  
  126. void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) {
  127.         if (dpcd[DP_TRAINING_AUX_RD_INTERVAL] == 0)
  128.                 udelay(400);
  129.         else
  130.                 mdelay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] * 4);
  131. }
  132. EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay);
  133.  
  134. u8 drm_dp_link_rate_to_bw_code(int link_rate)
  135. {
  136.         switch (link_rate) {
  137.         case 162000:
  138.         default:
  139.                 return DP_LINK_BW_1_62;
  140.         case 270000:
  141.                 return DP_LINK_BW_2_7;
  142.         case 540000:
  143.                 return DP_LINK_BW_5_4;
  144.         }
  145. }
  146. EXPORT_SYMBOL(drm_dp_link_rate_to_bw_code);
  147.  
  148. int drm_dp_bw_code_to_link_rate(u8 link_bw)
  149. {
  150.         switch (link_bw) {
  151.         case DP_LINK_BW_1_62:
  152.         default:
  153.                 return 162000;
  154.         case DP_LINK_BW_2_7:
  155.                 return 270000;
  156.         case DP_LINK_BW_5_4:
  157.                 return 540000;
  158.         }
  159. }
  160. EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate);
  161.  
  162. /**
  163.  * DOC: dp helpers
  164.  *
  165.  * The DisplayPort AUX channel is an abstraction to allow generic, driver-
  166.  * independent access to AUX functionality. Drivers can take advantage of
  167.  * this by filling in the fields of the drm_dp_aux structure.
  168.  *
  169.  * Transactions are described using a hardware-independent drm_dp_aux_msg
  170.  * structure, which is passed into a driver's .transfer() implementation.
  171.  * Both native and I2C-over-AUX transactions are supported.
  172.  */
  173.  
  174. static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
  175.                               unsigned int offset, void *buffer, size_t size)
  176. {
  177.         struct drm_dp_aux_msg msg;
  178.         unsigned int retry;
  179.         int err;
  180.  
  181.         memset(&msg, 0, sizeof(msg));
  182.         msg.address = offset;
  183.         msg.request = request;
  184.         msg.buffer = buffer;
  185.         msg.size = size;
  186.  
  187.         /*
  188.          * The specification doesn't give any recommendation on how often to
  189.          * retry native transactions. We used to retry 7 times like for
  190.          * aux i2c transactions but real world devices this wasn't
  191.          * sufficient, bump to 32 which makes Dell 4k monitors happier.
  192.          */
  193.         for (retry = 0; retry < 32; retry++) {
  194.  
  195.                 mutex_lock(&aux->hw_mutex);
  196.                 err = aux->transfer(aux, &msg);
  197.                 mutex_unlock(&aux->hw_mutex);
  198.                 if (err < 0) {
  199.                         if (err == -EBUSY)
  200.                                 continue;
  201.  
  202.                         return err;
  203.                 }
  204.  
  205.  
  206.                 switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) {
  207.                 case DP_AUX_NATIVE_REPLY_ACK:
  208.                         if (err < size)
  209.                                 return -EPROTO;
  210.                         return err;
  211.  
  212.                 case DP_AUX_NATIVE_REPLY_NACK:
  213.                         return -EIO;
  214.  
  215.                 case DP_AUX_NATIVE_REPLY_DEFER:
  216.                         usleep(500);
  217.                         break;
  218.                 }
  219.         }
  220.  
  221.         DRM_DEBUG_KMS("too many retries, giving up\n");
  222.         return -EIO;
  223. }
  224.  
  225. /**
  226.  * drm_dp_dpcd_read() - read a series of bytes from the DPCD
  227.  * @aux: DisplayPort AUX channel
  228.  * @offset: address of the (first) register to read
  229.  * @buffer: buffer to store the register values
  230.  * @size: number of bytes in @buffer
  231.  *
  232.  * Returns the number of bytes transferred on success, or a negative error
  233.  * code on failure. -EIO is returned if the request was NAKed by the sink or
  234.  * if the retry count was exceeded. If not all bytes were transferred, this
  235.  * function returns -EPROTO. Errors from the underlying AUX channel transfer
  236.  * function, with the exception of -EBUSY (which causes the transaction to
  237.  * be retried), are propagated to the caller.
  238.  */
  239. ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
  240.                          void *buffer, size_t size)
  241. {
  242.         return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset, buffer,
  243.                                   size);
  244. }
  245. EXPORT_SYMBOL(drm_dp_dpcd_read);
  246.  
  247. /**
  248.  * drm_dp_dpcd_write() - write a series of bytes to the DPCD
  249.  * @aux: DisplayPort AUX channel
  250.  * @offset: address of the (first) register to write
  251.  * @buffer: buffer containing the values to write
  252.  * @size: number of bytes in @buffer
  253.  *
  254.  * Returns the number of bytes transferred on success, or a negative error
  255.  * code on failure. -EIO is returned if the request was NAKed by the sink or
  256.  * if the retry count was exceeded. If not all bytes were transferred, this
  257.  * function returns -EPROTO. Errors from the underlying AUX channel transfer
  258.  * function, with the exception of -EBUSY (which causes the transaction to
  259.  * be retried), are propagated to the caller.
  260.  */
  261. ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset,
  262.                           void *buffer, size_t size)
  263. {
  264.         return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer,
  265.                                   size);
  266. }
  267. EXPORT_SYMBOL(drm_dp_dpcd_write);
  268.  
  269. /**
  270.  * drm_dp_dpcd_read_link_status() - read DPCD link status (bytes 0x202-0x207)
  271.  * @aux: DisplayPort AUX channel
  272.  * @status: buffer to store the link status in (must be at least 6 bytes)
  273.  *
  274.  * Returns the number of bytes transferred on success or a negative error
  275.  * code on failure.
  276.  */
  277. int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
  278.                                  u8 status[DP_LINK_STATUS_SIZE])
  279. {
  280.         return drm_dp_dpcd_read(aux, DP_LANE0_1_STATUS, status,
  281.                                 DP_LINK_STATUS_SIZE);
  282. }
  283. EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
  284.  
  285. /**
  286.  * drm_dp_link_probe() - probe a DisplayPort link for capabilities
  287.  * @aux: DisplayPort AUX channel
  288.  * @link: pointer to structure in which to return link capabilities
  289.  *
  290.  * The structure filled in by this function can usually be passed directly
  291.  * into drm_dp_link_power_up() and drm_dp_link_configure() to power up and
  292.  * configure the link based on the link's capabilities.
  293.  *
  294.  * Returns 0 on success or a negative error code on failure.
  295.  */
  296. int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link)
  297. {
  298.         u8 values[3];
  299.         int err;
  300.  
  301.         memset(link, 0, sizeof(*link));
  302.  
  303.         err = drm_dp_dpcd_read(aux, DP_DPCD_REV, values, sizeof(values));
  304.         if (err < 0)
  305.                 return err;
  306.  
  307.         link->revision = values[0];
  308.         link->rate = drm_dp_bw_code_to_link_rate(values[1]);
  309.         link->num_lanes = values[2] & DP_MAX_LANE_COUNT_MASK;
  310.  
  311.         if (values[2] & DP_ENHANCED_FRAME_CAP)
  312.                 link->capabilities |= DP_LINK_CAP_ENHANCED_FRAMING;
  313.  
  314.         return 0;
  315. }
  316. EXPORT_SYMBOL(drm_dp_link_probe);
  317.  
  318. /**
  319.  * drm_dp_link_power_up() - power up a DisplayPort link
  320.  * @aux: DisplayPort AUX channel
  321.  * @link: pointer to a structure containing the link configuration
  322.  *
  323.  * Returns 0 on success or a negative error code on failure.
  324.  */
  325. int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link)
  326. {
  327.         u8 value;
  328.         int err;
  329.  
  330.         /* DP_SET_POWER register is only available on DPCD v1.1 and later */
  331.         if (link->revision < 0x11)
  332.                 return 0;
  333.  
  334.         err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
  335.         if (err < 0)
  336.                 return err;
  337.  
  338.         value &= ~DP_SET_POWER_MASK;
  339.         value |= DP_SET_POWER_D0;
  340.  
  341.         err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
  342.         if (err < 0)
  343.                 return err;
  344.  
  345.         /*
  346.          * According to the DP 1.1 specification, a "Sink Device must exit the
  347.          * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink
  348.          * Control Field" (register 0x600).
  349.          */
  350.         usleep(2000);
  351.  
  352.         return 0;
  353. }
  354. EXPORT_SYMBOL(drm_dp_link_power_up);
  355.  
  356. /**
  357.  * drm_dp_link_configure() - configure a DisplayPort link
  358.  * @aux: DisplayPort AUX channel
  359.  * @link: pointer to a structure containing the link configuration
  360.  *
  361.  * Returns 0 on success or a negative error code on failure.
  362.  */
  363. int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link)
  364. {
  365.         u8 values[2];
  366.         int err;
  367.  
  368.         values[0] = drm_dp_link_rate_to_bw_code(link->rate);
  369.         values[1] = link->num_lanes;
  370.  
  371.         if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
  372.                 values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
  373.  
  374.         err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values));
  375.         if (err < 0)
  376.                 return err;
  377.  
  378.         return 0;
  379. }
  380. EXPORT_SYMBOL(drm_dp_link_configure);
  381.  
  382. /*
  383.  * I2C-over-AUX implementation
  384.  */
  385.  
  386. static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter)
  387. {
  388.         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
  389.                I2C_FUNC_SMBUS_READ_BLOCK_DATA |
  390.                I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
  391.                I2C_FUNC_10BIT_ADDR;
  392. }
  393.  
  394. /*
  395.  * Transfer a single I2C-over-AUX message and handle various error conditions,
  396.  * retrying the transaction as appropriate.  It is assumed that the
  397.  * aux->transfer function does not modify anything in the msg other than the
  398.  * reply field.
  399.  */
  400. static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
  401. {
  402.         unsigned int retry;
  403.         int err;
  404.  
  405.         /*
  406.          * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device
  407.          * is required to retry at least seven times upon receiving AUX_DEFER
  408.          * before giving up the AUX transaction.
  409.          */
  410.         for (retry = 0; retry < 7; retry++) {
  411.                 mutex_lock(&aux->hw_mutex);
  412.                 err = aux->transfer(aux, msg);
  413.                 mutex_unlock(&aux->hw_mutex);
  414.                 if (err < 0) {
  415.                         if (err == -EBUSY)
  416.                                 continue;
  417.  
  418.                         DRM_DEBUG_KMS("transaction failed: %d\n", err);
  419.                         return err;
  420.                 }
  421.  
  422.  
  423.                 switch (msg->reply & DP_AUX_NATIVE_REPLY_MASK) {
  424.                 case DP_AUX_NATIVE_REPLY_ACK:
  425.                         /*
  426.                          * For I2C-over-AUX transactions this isn't enough, we
  427.                          * need to check for the I2C ACK reply.
  428.                          */
  429.                         break;
  430.  
  431.                 case DP_AUX_NATIVE_REPLY_NACK:
  432.                         DRM_DEBUG_KMS("native nack\n");
  433.                         return -EREMOTEIO;
  434.  
  435.                 case DP_AUX_NATIVE_REPLY_DEFER:
  436.                         DRM_DEBUG_KMS("native defer");
  437.                         /*
  438.                          * We could check for I2C bit rate capabilities and if
  439.                          * available adjust this interval. We could also be
  440.                          * more careful with DP-to-legacy adapters where a
  441.                          * long legacy cable may force very low I2C bit rates.
  442.                          *
  443.                          * For now just defer for long enough to hopefully be
  444.                          * safe for all use-cases.
  445.                          */
  446.                         usleep_range(500, 600);
  447.                         continue;
  448.  
  449.                 default:
  450.                         DRM_ERROR("invalid native reply %#04x\n", msg->reply);
  451.                         return -EREMOTEIO;
  452.                 }
  453.  
  454.                 switch (msg->reply & DP_AUX_I2C_REPLY_MASK) {
  455.                 case DP_AUX_I2C_REPLY_ACK:
  456.                         /*
  457.                          * Both native ACK and I2C ACK replies received. We
  458.                          * can assume the transfer was successful.
  459.                          */
  460.                         if (err < msg->size)
  461.                                 return -EPROTO;
  462.                         return 0;
  463.  
  464.                 case DP_AUX_I2C_REPLY_NACK:
  465.                         DRM_DEBUG_KMS("I2C nack\n");
  466.                         return -EREMOTEIO;
  467.  
  468.                 case DP_AUX_I2C_REPLY_DEFER:
  469.                         DRM_DEBUG_KMS("I2C defer\n");
  470.                         usleep_range(400, 500);
  471.                         continue;
  472.  
  473.                 default:
  474.                         DRM_ERROR("invalid I2C reply %#04x\n", msg->reply);
  475.                         return -EREMOTEIO;
  476.                 }
  477.         }
  478.  
  479.         DRM_DEBUG_KMS("too many retries, giving up\n");
  480.         return -EREMOTEIO;
  481. }
  482.  
  483. static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
  484.                            int num)
  485. {
  486.         struct drm_dp_aux *aux = adapter->algo_data;
  487.         unsigned int i, j;
  488.         struct drm_dp_aux_msg msg;
  489.         int err = 0;
  490.  
  491.         memset(&msg, 0, sizeof(msg));
  492.  
  493.         for (i = 0; i < num; i++) {
  494.                 msg.address = msgs[i].addr;
  495.                 msg.request = (msgs[i].flags & I2C_M_RD) ?
  496.                         DP_AUX_I2C_READ :
  497.                         DP_AUX_I2C_WRITE;
  498.                 msg.request |= DP_AUX_I2C_MOT;
  499.                 /* Send a bare address packet to start the transaction.
  500.                  * Zero sized messages specify an address only (bare
  501.                  * address) transaction.
  502.                  */
  503.                 msg.buffer = NULL;
  504.                 msg.size = 0;
  505.                 err = drm_dp_i2c_do_msg(aux, &msg);
  506.                 if (err < 0)
  507.                         break;
  508.                 /*
  509.                  * Many hardware implementations support FIFOs larger than a
  510.                  * single byte, but it has been empirically determined that
  511.                  * transferring data in larger chunks can actually lead to
  512.                  * decreased performance. Therefore each message is simply
  513.                  * transferred byte-by-byte.
  514.                  */
  515.                 for (j = 0; j < msgs[i].len; j++) {
  516.                         msg.buffer = msgs[i].buf + j;
  517.                         msg.size = 1;
  518.  
  519.                         err = drm_dp_i2c_do_msg(aux, &msg);
  520.                         if (err < 0)
  521.                                 break;
  522.                 }
  523.                 if (err < 0)
  524.                         break;
  525.         }
  526.         if (err >= 0)
  527.                 err = num;
  528.         /* Send a bare address packet to close out the transaction.
  529.          * Zero sized messages specify an address only (bare
  530.          * address) transaction.
  531.          */
  532.         msg.request &= ~DP_AUX_I2C_MOT;
  533.         msg.buffer = NULL;
  534.         msg.size = 0;
  535.         (void)drm_dp_i2c_do_msg(aux, &msg);
  536.  
  537.         return err;
  538. }
  539.  
  540. static const struct i2c_algorithm drm_dp_i2c_algo = {
  541.         .functionality = drm_dp_i2c_functionality,
  542.         .master_xfer = drm_dp_i2c_xfer,
  543. };
  544.  
  545. /**
  546.  * drm_dp_aux_register() - initialise and register aux channel
  547.  * @aux: DisplayPort AUX channel
  548.  *
  549.  * Returns 0 on success or a negative error code on failure.
  550.  */
  551. int drm_dp_aux_register(struct drm_dp_aux *aux)
  552. {
  553.         mutex_init(&aux->hw_mutex);
  554.  
  555.         aux->ddc.algo = &drm_dp_i2c_algo;
  556.         aux->ddc.algo_data = aux;
  557.         aux->ddc.retries = 3;
  558.  
  559.         aux->ddc.class = I2C_CLASS_DDC;
  560.         aux->ddc.owner = THIS_MODULE;
  561.         aux->ddc.dev.parent = aux->dev;
  562. //      aux->ddc.dev.of_node = aux->dev->of_node;
  563.  
  564.     strlcpy(aux->ddc.name, aux->name ? aux->name : "aux",
  565.                 sizeof(aux->ddc.name));
  566.  
  567.         return i2c_add_adapter(&aux->ddc);
  568. }
  569. EXPORT_SYMBOL(drm_dp_aux_register);
  570.  
  571. /**
  572.  * drm_dp_aux_unregister() - unregister an AUX adapter
  573.  * @aux: DisplayPort AUX channel
  574.  */
  575. void drm_dp_aux_unregister(struct drm_dp_aux *aux)
  576. {
  577.         i2c_del_adapter(&aux->ddc);
  578. }
  579. EXPORT_SYMBOL(drm_dp_aux_unregister);
  580.