Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  *
  3.  * Copyright (c) 2012 Gilles Dartiguelongue, Thomas Richter
  4.  *
  5.  * All Rights Reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the
  9.  * "Software"), to deal in the Software without restriction, including
  10.  * without limitation the rights to use, copy, modify, merge, publish,
  11.  * distribute, sub license, and/or sell copies of the Software, and to
  12.  * permit persons to whom the Software is furnished to do so, subject to
  13.  * the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice (including the
  16.  * next paragraph) shall be included in all copies or substantial portions
  17.  * of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  21.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  22.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  23.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  24.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  25.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26.  *
  27.  */
  28.  
  29. #include "dvo.h"
  30. #include "i915_reg.h"
  31. #include "i915_drv.h"
  32.  
  33. #define NS2501_VID 0x1305
  34. #define NS2501_DID 0x6726
  35.  
  36. #define NS2501_VID_LO 0x00
  37. #define NS2501_VID_HI 0x01
  38. #define NS2501_DID_LO 0x02
  39. #define NS2501_DID_HI 0x03
  40. #define NS2501_REV 0x04
  41. #define NS2501_RSVD 0x05
  42. #define NS2501_FREQ_LO 0x06
  43. #define NS2501_FREQ_HI 0x07
  44.  
  45. #define NS2501_REG8 0x08
  46. #define NS2501_8_VEN (1<<5)
  47. #define NS2501_8_HEN (1<<4)
  48. #define NS2501_8_DSEL (1<<3)
  49. #define NS2501_8_BPAS (1<<2)
  50. #define NS2501_8_RSVD (1<<1)
  51. #define NS2501_8_PD (1<<0)
  52.  
  53. #define NS2501_REG9 0x09
  54. #define NS2501_9_VLOW (1<<7)
  55. #define NS2501_9_MSEL_MASK (0x7<<4)
  56. #define NS2501_9_TSEL (1<<3)
  57. #define NS2501_9_RSEN (1<<2)
  58. #define NS2501_9_RSVD (1<<1)
  59. #define NS2501_9_MDI (1<<0)
  60.  
  61. #define NS2501_REGC 0x0c
  62.  
  63. struct ns2501_priv {
  64.         //I2CDevRec d;
  65.         bool quiet;
  66.         int reg_8_shadow;
  67.         int reg_8_set;
  68.         // Shadow registers for i915
  69.         int dvoc;
  70.         int pll_a;
  71.         int srcdim;
  72.         int fw_blc;
  73. };
  74.  
  75. #define NSPTR(d) ((NS2501Ptr)(d->DriverPrivate.ptr))
  76.  
  77. /*
  78.  * For reasons unclear to me, the ns2501 at least on the Fujitsu/Siemens
  79.  * laptops does not react on the i2c bus unless
  80.  * both the PLL is running and the display is configured in its native
  81.  * resolution.
  82.  * This function forces the DVO on, and stores the registers it touches.
  83.  * Afterwards, registers are restored to regular values.
  84.  *
  85.  * This is pretty much a hack, though it works.
  86.  * Without that, ns2501_readb and ns2501_writeb fail
  87.  * when switching the resolution.
  88.  */
  89.  
  90. static void enable_dvo(struct intel_dvo_device *dvo)
  91. {
  92.         struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
  93.         struct i2c_adapter *adapter = dvo->i2c_bus;
  94.         struct intel_gmbus *bus = container_of(adapter,
  95.                                                struct intel_gmbus,
  96.                                                adapter);
  97.         struct drm_i915_private *dev_priv = bus->dev_priv;
  98.  
  99.         DRM_DEBUG_KMS("%s: Trying to re-enable the DVO\n", __FUNCTION__);
  100.  
  101.         ns->dvoc = I915_READ(DVO_C);
  102.         ns->pll_a = I915_READ(_DPLL_A);
  103.         ns->srcdim = I915_READ(DVOC_SRCDIM);
  104.         ns->fw_blc = I915_READ(FW_BLC);
  105.  
  106.         I915_WRITE(DVOC, 0x10004084);
  107.         I915_WRITE(_DPLL_A, 0xd0820000);
  108.         I915_WRITE(DVOC_SRCDIM, 0x400300);      // 1024x768
  109.         I915_WRITE(FW_BLC, 0x1080304);
  110.  
  111.         I915_WRITE(DVOC, 0x90004084);
  112. }
  113.  
  114. /*
  115.  * Restore the I915 registers modified by the above
  116.  * trigger function.
  117.  */
  118. static void restore_dvo(struct intel_dvo_device *dvo)
  119. {
  120.         struct i2c_adapter *adapter = dvo->i2c_bus;
  121.         struct intel_gmbus *bus = container_of(adapter,
  122.                                                struct intel_gmbus,
  123.                                                adapter);
  124.         struct drm_i915_private *dev_priv = bus->dev_priv;
  125.         struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
  126.  
  127.         I915_WRITE(DVOC, ns->dvoc);
  128.         I915_WRITE(_DPLL_A, ns->pll_a);
  129.         I915_WRITE(DVOC_SRCDIM, ns->srcdim);
  130.         I915_WRITE(FW_BLC, ns->fw_blc);
  131. }
  132.  
  133. /*
  134. ** Read a register from the ns2501.
  135. ** Returns true if successful, false otherwise.
  136. ** If it returns false, it might be wise to enable the
  137. ** DVO with the above function.
  138. */
  139. static bool ns2501_readb(struct intel_dvo_device *dvo, int addr, uint8_t * ch)
  140. {
  141.         struct ns2501_priv *ns = dvo->dev_priv;
  142.         struct i2c_adapter *adapter = dvo->i2c_bus;
  143.         u8 out_buf[2];
  144.         u8 in_buf[2];
  145.  
  146.         struct i2c_msg msgs[] = {
  147.                 {
  148.                  .addr = dvo->slave_addr,
  149.                  .flags = 0,
  150.                  .len = 1,
  151.                  .buf = out_buf,
  152.                  },
  153.                 {
  154.                  .addr = dvo->slave_addr,
  155.                  .flags = I2C_M_RD,
  156.                  .len = 1,
  157.                  .buf = in_buf,
  158.                  }
  159.         };
  160.  
  161.         out_buf[0] = addr;
  162.         out_buf[1] = 0;
  163.  
  164.         if (i2c_transfer(adapter, msgs, 2) == 2) {
  165.                 *ch = in_buf[0];
  166.                 return true;
  167.         };
  168.  
  169.         if (!ns->quiet) {
  170.                 DRM_DEBUG_KMS
  171.                     ("Unable to read register 0x%02x from %s:0x%02x.\n", addr,
  172.                      adapter->name, dvo->slave_addr);
  173.         }
  174.  
  175.         return false;
  176. }
  177.  
  178. /*
  179. ** Write a register to the ns2501.
  180. ** Returns true if successful, false otherwise.
  181. ** If it returns false, it might be wise to enable the
  182. ** DVO with the above function.
  183. */
  184. static bool ns2501_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
  185. {
  186.         struct ns2501_priv *ns = dvo->dev_priv;
  187.         struct i2c_adapter *adapter = dvo->i2c_bus;
  188.         uint8_t out_buf[2];
  189.  
  190.         struct i2c_msg msg = {
  191.                 .addr = dvo->slave_addr,
  192.                 .flags = 0,
  193.                 .len = 2,
  194.                 .buf = out_buf,
  195.         };
  196.  
  197.         out_buf[0] = addr;
  198.         out_buf[1] = ch;
  199.  
  200.         if (i2c_transfer(adapter, &msg, 1) == 1) {
  201.                 return true;
  202.         }
  203.  
  204.         if (!ns->quiet) {
  205.                 DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d\n",
  206.                               addr, adapter->name, dvo->slave_addr);
  207.         }
  208.  
  209.         return false;
  210. }
  211.  
  212. /* National Semiconductor 2501 driver for chip on i2c bus
  213.  * scan for the chip on the bus.
  214.  * Hope the VBIOS initialized the PLL correctly so we can
  215.  * talk to it. If not, it will not be seen and not detected.
  216.  * Bummer!
  217.  */
  218. static bool ns2501_init(struct intel_dvo_device *dvo,
  219.                         struct i2c_adapter *adapter)
  220. {
  221.         /* this will detect the NS2501 chip on the specified i2c bus */
  222.         struct ns2501_priv *ns;
  223.         unsigned char ch;
  224.  
  225.         ns = kzalloc(sizeof(struct ns2501_priv), GFP_KERNEL);
  226.         if (ns == NULL)
  227.                 return false;
  228.  
  229.         dvo->i2c_bus = adapter;
  230.         dvo->dev_priv = ns;
  231.         ns->quiet = true;
  232.  
  233.         if (!ns2501_readb(dvo, NS2501_VID_LO, &ch))
  234.                 goto out;
  235.  
  236.         if (ch != (NS2501_VID & 0xff)) {
  237.                 DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
  238.                               ch, adapter->name, dvo->slave_addr);
  239.                 goto out;
  240.         }
  241.  
  242.         if (!ns2501_readb(dvo, NS2501_DID_LO, &ch))
  243.                 goto out;
  244.  
  245.         if (ch != (NS2501_DID & 0xff)) {
  246.                 DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
  247.                               ch, adapter->name, dvo->slave_addr);
  248.                 goto out;
  249.         }
  250.         ns->quiet = false;
  251.         ns->reg_8_set = 0;
  252.         ns->reg_8_shadow =
  253.             NS2501_8_PD | NS2501_8_BPAS | NS2501_8_VEN | NS2501_8_HEN;
  254.  
  255.         DRM_DEBUG_KMS("init ns2501 dvo controller successfully!\n");
  256.         return true;
  257.  
  258. out:
  259.         kfree(ns);
  260.         return false;
  261. }
  262.  
  263. static enum drm_connector_status ns2501_detect(struct intel_dvo_device *dvo)
  264. {
  265.         /*
  266.          * This is a Laptop display, it doesn't have hotplugging.
  267.          * Even if not, the detection bit of the 2501 is unreliable as
  268.          * it only works for some display types.
  269.          * It is even more unreliable as the PLL must be active for
  270.          * allowing reading from the chiop.
  271.          */
  272.         return connector_status_connected;
  273. }
  274.  
  275. static enum drm_mode_status ns2501_mode_valid(struct intel_dvo_device *dvo,
  276.                                               struct drm_display_mode *mode)
  277. {
  278.         DRM_DEBUG_KMS
  279.             ("%s: is mode valid (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d)\n",
  280.              __FUNCTION__, mode->hdisplay, mode->htotal, mode->vdisplay,
  281.              mode->vtotal);
  282.  
  283.         /*
  284.          * Currently, these are all the modes I have data from.
  285.          * More might exist. Unclear how to find the native resolution
  286.          * of the panel in here so we could always accept it
  287.          * by disabling the scaler.
  288.          */
  289.         if ((mode->hdisplay == 800 && mode->vdisplay == 600) ||
  290.             (mode->hdisplay == 640 && mode->vdisplay == 480) ||
  291.             (mode->hdisplay == 1024 && mode->vdisplay == 768)) {
  292.                 return MODE_OK;
  293.         } else {
  294.                 return MODE_ONE_SIZE;   /* Is this a reasonable error? */
  295.         }
  296. }
  297.  
  298. static void ns2501_mode_set(struct intel_dvo_device *dvo,
  299.                             struct drm_display_mode *mode,
  300.                             struct drm_display_mode *adjusted_mode)
  301. {
  302.         bool ok;
  303.         bool restore = false;
  304.         struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
  305.  
  306.         DRM_DEBUG_KMS
  307.             ("%s: set mode (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n",
  308.              __FUNCTION__, mode->hdisplay, mode->htotal, mode->vdisplay,
  309.              mode->vtotal);
  310.  
  311.         /*
  312.          * Where do I find the native resolution for which scaling is not required???
  313.          *
  314.          * First trigger the DVO on as otherwise the chip does not appear on the i2c
  315.          * bus.
  316.          */
  317.         do {
  318.                 ok = true;
  319.  
  320.                 if (mode->hdisplay == 800 && mode->vdisplay == 600) {
  321.                         /* mode 277 */
  322.                         ns->reg_8_shadow &= ~NS2501_8_BPAS;
  323.                         DRM_DEBUG_KMS("%s: switching to 800x600\n",
  324.                                       __FUNCTION__);
  325.  
  326.                         /*
  327.                          * No, I do not know where this data comes from.
  328.                          * It is just what the video bios left in the DVO, so
  329.                          * I'm just copying it here over.
  330.                          * This also means that I cannot support any other modes
  331.                          * except the ones supported by the bios.
  332.                          */
  333.                         ok &= ns2501_writeb(dvo, 0x11, 0xc8);   // 0xc7 also works.
  334.                         ok &= ns2501_writeb(dvo, 0x1b, 0x19);
  335.                         ok &= ns2501_writeb(dvo, 0x1c, 0x62);   // VBIOS left 0x64 here, but 0x62 works nicer
  336.                         ok &= ns2501_writeb(dvo, 0x1d, 0x02);
  337.  
  338.                         ok &= ns2501_writeb(dvo, 0x34, 0x03);
  339.                         ok &= ns2501_writeb(dvo, 0x35, 0xff);
  340.  
  341.                         ok &= ns2501_writeb(dvo, 0x80, 0x27);
  342.                         ok &= ns2501_writeb(dvo, 0x81, 0x03);
  343.                         ok &= ns2501_writeb(dvo, 0x82, 0x41);
  344.                         ok &= ns2501_writeb(dvo, 0x83, 0x05);
  345.  
  346.                         ok &= ns2501_writeb(dvo, 0x8d, 0x02);
  347.                         ok &= ns2501_writeb(dvo, 0x8e, 0x04);
  348.                         ok &= ns2501_writeb(dvo, 0x8f, 0x00);
  349.  
  350.                         ok &= ns2501_writeb(dvo, 0x90, 0xfe);   /* vertical. VBIOS left 0xff here, but 0xfe works better */
  351.                         ok &= ns2501_writeb(dvo, 0x91, 0x07);
  352.                         ok &= ns2501_writeb(dvo, 0x94, 0x00);
  353.                         ok &= ns2501_writeb(dvo, 0x95, 0x00);
  354.  
  355.                         ok &= ns2501_writeb(dvo, 0x96, 0x00);
  356.  
  357.                         ok &= ns2501_writeb(dvo, 0x99, 0x00);
  358.                         ok &= ns2501_writeb(dvo, 0x9a, 0x88);
  359.  
  360.                         ok &= ns2501_writeb(dvo, 0x9c, 0x23);   /* Looks like first and last line of the image. */
  361.                         ok &= ns2501_writeb(dvo, 0x9d, 0x00);
  362.                         ok &= ns2501_writeb(dvo, 0x9e, 0x25);
  363.                         ok &= ns2501_writeb(dvo, 0x9f, 0x03);
  364.  
  365.                         ok &= ns2501_writeb(dvo, 0xa4, 0x80);
  366.  
  367.                         ok &= ns2501_writeb(dvo, 0xb6, 0x00);
  368.  
  369.                         ok &= ns2501_writeb(dvo, 0xb9, 0xc8);   /* horizontal? */
  370.                         ok &= ns2501_writeb(dvo, 0xba, 0x00);   /* horizontal? */
  371.  
  372.                         ok &= ns2501_writeb(dvo, 0xc0, 0x05);   /* horizontal? */
  373.                         ok &= ns2501_writeb(dvo, 0xc1, 0xd7);
  374.  
  375.                         ok &= ns2501_writeb(dvo, 0xc2, 0x00);
  376.                         ok &= ns2501_writeb(dvo, 0xc3, 0xf8);
  377.  
  378.                         ok &= ns2501_writeb(dvo, 0xc4, 0x03);
  379.                         ok &= ns2501_writeb(dvo, 0xc5, 0x1a);
  380.  
  381.                         ok &= ns2501_writeb(dvo, 0xc6, 0x00);
  382.                         ok &= ns2501_writeb(dvo, 0xc7, 0x73);
  383.                         ok &= ns2501_writeb(dvo, 0xc8, 0x02);
  384.  
  385.                 } else if (mode->hdisplay == 640 && mode->vdisplay == 480) {
  386.                         /* mode 274 */
  387.                         DRM_DEBUG_KMS("%s: switching to 640x480\n",
  388.                                       __FUNCTION__);
  389.                         /*
  390.                          * No, I do not know where this data comes from.
  391.                          * It is just what the video bios left in the DVO, so
  392.                          * I'm just copying it here over.
  393.                          * This also means that I cannot support any other modes
  394.                          * except the ones supported by the bios.
  395.                          */
  396.                         ns->reg_8_shadow &= ~NS2501_8_BPAS;
  397.  
  398.                         ok &= ns2501_writeb(dvo, 0x11, 0xa0);
  399.                         ok &= ns2501_writeb(dvo, 0x1b, 0x11);
  400.                         ok &= ns2501_writeb(dvo, 0x1c, 0x54);
  401.                         ok &= ns2501_writeb(dvo, 0x1d, 0x03);
  402.  
  403.                         ok &= ns2501_writeb(dvo, 0x34, 0x03);
  404.                         ok &= ns2501_writeb(dvo, 0x35, 0xff);
  405.  
  406.                         ok &= ns2501_writeb(dvo, 0x80, 0xff);
  407.                         ok &= ns2501_writeb(dvo, 0x81, 0x07);
  408.                         ok &= ns2501_writeb(dvo, 0x82, 0x3d);
  409.                         ok &= ns2501_writeb(dvo, 0x83, 0x05);
  410.  
  411.                         ok &= ns2501_writeb(dvo, 0x8d, 0x02);
  412.                         ok &= ns2501_writeb(dvo, 0x8e, 0x10);
  413.                         ok &= ns2501_writeb(dvo, 0x8f, 0x00);
  414.  
  415.                         ok &= ns2501_writeb(dvo, 0x90, 0xff);   /* vertical */
  416.                         ok &= ns2501_writeb(dvo, 0x91, 0x07);
  417.                         ok &= ns2501_writeb(dvo, 0x94, 0x00);
  418.                         ok &= ns2501_writeb(dvo, 0x95, 0x00);
  419.  
  420.                         ok &= ns2501_writeb(dvo, 0x96, 0x05);
  421.  
  422.                         ok &= ns2501_writeb(dvo, 0x99, 0x00);
  423.                         ok &= ns2501_writeb(dvo, 0x9a, 0x88);
  424.  
  425.                         ok &= ns2501_writeb(dvo, 0x9c, 0x24);
  426.                         ok &= ns2501_writeb(dvo, 0x9d, 0x00);
  427.                         ok &= ns2501_writeb(dvo, 0x9e, 0x25);
  428.                         ok &= ns2501_writeb(dvo, 0x9f, 0x03);
  429.  
  430.                         ok &= ns2501_writeb(dvo, 0xa4, 0x84);
  431.  
  432.                         ok &= ns2501_writeb(dvo, 0xb6, 0x09);
  433.  
  434.                         ok &= ns2501_writeb(dvo, 0xb9, 0xa0);   /* horizontal? */
  435.                         ok &= ns2501_writeb(dvo, 0xba, 0x00);   /* horizontal? */
  436.  
  437.                         ok &= ns2501_writeb(dvo, 0xc0, 0x05);   /* horizontal? */
  438.                         ok &= ns2501_writeb(dvo, 0xc1, 0x90);
  439.  
  440.                         ok &= ns2501_writeb(dvo, 0xc2, 0x00);
  441.                         ok &= ns2501_writeb(dvo, 0xc3, 0x0f);
  442.  
  443.                         ok &= ns2501_writeb(dvo, 0xc4, 0x03);
  444.                         ok &= ns2501_writeb(dvo, 0xc5, 0x16);
  445.  
  446.                         ok &= ns2501_writeb(dvo, 0xc6, 0x00);
  447.                         ok &= ns2501_writeb(dvo, 0xc7, 0x02);
  448.                         ok &= ns2501_writeb(dvo, 0xc8, 0x02);
  449.  
  450.                 } else if (mode->hdisplay == 1024 && mode->vdisplay == 768) {
  451.                         /* mode 280 */
  452.                         DRM_DEBUG_KMS("%s: switching to 1024x768\n",
  453.                                       __FUNCTION__);
  454.                         /*
  455.                          * This might or might not work, actually. I'm silently
  456.                          * assuming here that the native panel resolution is
  457.                          * 1024x768. If not, then this leaves the scaler disabled
  458.                          * generating a picture that is likely not the expected.
  459.                          *
  460.                          * Problem is that I do not know where to take the panel
  461.                          * dimensions from.
  462.                          *
  463.                          * Enable the bypass, scaling not required.
  464.                          *
  465.                          * The scaler registers are irrelevant here....
  466.                          *
  467.                          */
  468.                         ns->reg_8_shadow |= NS2501_8_BPAS;
  469.                         ok &= ns2501_writeb(dvo, 0x37, 0x44);
  470.                 } else {
  471.                         /*
  472.                          * Data not known. Bummer!
  473.                          * Hopefully, the code should not go here
  474.                          * as mode_OK delivered no other modes.
  475.                          */
  476.                         ns->reg_8_shadow |= NS2501_8_BPAS;
  477.                 }
  478.                 ok &= ns2501_writeb(dvo, NS2501_REG8, ns->reg_8_shadow);
  479.  
  480.                 if (!ok) {
  481.                         if (restore)
  482.                                 restore_dvo(dvo);
  483.                         enable_dvo(dvo);
  484.                         restore = true;
  485.                 }
  486.         } while (!ok);
  487.         /*
  488.          * Restore the old i915 registers before
  489.          * forcing the ns2501 on.
  490.          */
  491.         if (restore)
  492.                 restore_dvo(dvo);
  493. }
  494.  
  495. /* set the NS2501 power state */
  496. static bool ns2501_get_hw_state(struct intel_dvo_device *dvo)
  497. {
  498.         unsigned char ch;
  499.  
  500.         if (!ns2501_readb(dvo, NS2501_REG8, &ch))
  501.                 return false;
  502.  
  503.         if (ch & NS2501_8_PD)
  504.                 return true;
  505.         else
  506.                 return false;
  507. }
  508.  
  509. /* set the NS2501 power state */
  510. static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
  511. {
  512.         bool ok;
  513.         bool restore = false;
  514.         struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
  515.         unsigned char ch;
  516.  
  517.         DRM_DEBUG_KMS("%s: Trying set the dpms of the DVO to %i\n",
  518.                       __FUNCTION__, enable);
  519.  
  520.         ch = ns->reg_8_shadow;
  521.  
  522.         if (enable)
  523.                 ch |= NS2501_8_PD;
  524.         else
  525.                 ch &= ~NS2501_8_PD;
  526.  
  527.         if (ns->reg_8_set == 0 || ns->reg_8_shadow != ch) {
  528.                 ns->reg_8_set = 1;
  529.                 ns->reg_8_shadow = ch;
  530.  
  531.                 do {
  532.                         ok = true;
  533.                         ok &= ns2501_writeb(dvo, NS2501_REG8, ch);
  534.                         ok &=
  535.                             ns2501_writeb(dvo, 0x34,
  536.                                           enable ? 0x03 : 0x00);
  537.                         ok &=
  538.                             ns2501_writeb(dvo, 0x35,
  539.                                           enable ? 0xff : 0x00);
  540.                         if (!ok) {
  541.                                 if (restore)
  542.                                         restore_dvo(dvo);
  543.                                 enable_dvo(dvo);
  544.                                 restore = true;
  545.                         }
  546.                 } while (!ok);
  547.  
  548.                 if (restore)
  549.                         restore_dvo(dvo);
  550.         }
  551. }
  552.  
  553. static void ns2501_dump_regs(struct intel_dvo_device *dvo)
  554. {
  555.         uint8_t val;
  556.  
  557.         ns2501_readb(dvo, NS2501_FREQ_LO, &val);
  558.         DRM_LOG_KMS("NS2501_FREQ_LO: 0x%02x\n", val);
  559.         ns2501_readb(dvo, NS2501_FREQ_HI, &val);
  560.         DRM_LOG_KMS("NS2501_FREQ_HI: 0x%02x\n", val);
  561.         ns2501_readb(dvo, NS2501_REG8, &val);
  562.         DRM_LOG_KMS("NS2501_REG8: 0x%02x\n", val);
  563.         ns2501_readb(dvo, NS2501_REG9, &val);
  564.         DRM_LOG_KMS("NS2501_REG9: 0x%02x\n", val);
  565.         ns2501_readb(dvo, NS2501_REGC, &val);
  566.         DRM_LOG_KMS("NS2501_REGC: 0x%02x\n", val);
  567. }
  568.  
  569. static void ns2501_destroy(struct intel_dvo_device *dvo)
  570. {
  571.         struct ns2501_priv *ns = dvo->dev_priv;
  572.  
  573.         if (ns) {
  574.                 kfree(ns);
  575.                 dvo->dev_priv = NULL;
  576.         }
  577. }
  578.  
  579. struct intel_dvo_dev_ops ns2501_ops = {
  580.         .init = ns2501_init,
  581.         .detect = ns2501_detect,
  582.         .mode_valid = ns2501_mode_valid,
  583.         .mode_set = ns2501_mode_set,
  584.         .dpms = ns2501_dpms,
  585.         .get_hw_state = ns2501_get_hw_state,
  586.         .dump_regs = ns2501_dump_regs,
  587.         .destroy = ns2501_destroy,
  588. };
  589.